目录
app安装方式
Android应用程序安装有四种方式:
- 系统启动时安装,没有安装界面
- 第三方应用安装,有安装界面,也是我们最熟悉的方式
- ADB命令安装,没有安装界面
- 通过Google Play市场安装,没有安装界面
四种方式最后都是通过PackageManagerService服务来完成应用程序的安装。
PackageManagerService服务通过与Installd服务通信,发送具体的指令来执行应用程序的安装、卸载等工作。
使用路径
app在安装时涉及到如下几个重要目录:
目录 | 解释 |
---|---|
system/app | 系统应用程序的目录 |
data/app | 用户程序安装的目录 |
data/data | 存放应用程序数据的目录 |
data/dalvik-cache | 存放的是经过优化的dex文件 |
APK文件结构
目录 | 描述 |
---|---|
assert | 存放的原生资源文件,通过AssetManager类访问 |
lib | native库文件 |
META-INF | 存放签名信息,用来保证APK包的完整性和系统的安全。系统安装APK时,应用管理器会按照对应算法对包里文件做校验,如果校验结果与META-INF中内容不一致,则不会安装这个APK。 |
res | 种资源文件系统会在R.java里面自动生成该资源文件的ID,所以访问这种资源文件比较简单,通过R.XXX.ID即可 |
AndroidManifest.xml | 每个应用都必须定义和包含,描述应用的名字、版本权限、引用的库文件等信息。apk中的AndroidManifest.xml经过压缩,可以通过AXMLPrinter2工具解开。 |
classes.dex | 是JAVA源码编译后生成的JAVA字节码文件。但Android使用的dalvik虚拟机与标准的JAVA虚拟机不兼容,dex文件与class文件相比,不论是文件结构还是opcode都不一样。 |
resources.arsc | 编译后的二进制资源文件。 |
应用程序安装过程
adb install:
安装入口函数为Pm.runInstall
frameworks\base\cmds\pm\src\com\android\commands\pm\Pm.java网络下载应用安装和第三方应用安装:
安装入口函数为ApplicationPackageManager.installPackage
frameworks\base\core\java\android\app\ApplicationPackageManager.java
apk安装的四大步骤:1. 拷贝apk到指定的目录:默认情况下,用户安装的apk首先会拷贝到/data/app下,用户有访问/data/app目录的权限,但系统出厂的apk文件会被放到/system分区下,包括/system/app,/system/vendor/app,以及/system/priv-app等,该分区需要root权限的用户才能访问。2. 加载apk、拷贝文件、创建应用的数据目录:为了加快APP的启动速度,apk在安装的时候,会首先将APP的可执行文件(dex)拷贝到/data/dalvik-cache目录下,缓存起来。再在/data/data/目录下创建应用程序的数据目录(以应用包名命令),用来存放应用的数据库、xml文件、cache、二进制的so动态库等。3. 解析apk的AndroidManifest.xml文件:在安装apk的过程中,会解析apk的AndroidManifest.xml文件,将apk的权限、应用包名、apk的安装位置、版本、userID等重要信息保存在/data/system/packages.xml文件中。这些操作都是在PackageManagerService中完成的。4. 显示icon图标:应用程序经过PMS中的逻辑处理后,相当于已经注册好了,如果想要在Android桌面上看到icon图标,则需要Launcher将系统中已经安装的程序展现在桌面上。
adb install 的安装方式
adb install 的安装方式,会调用| commandline.cpp |
中的adb_commandline函数:
- int adb_commandline(int argc, const char** argv) {
- ……
- else if (!strcmp(argv[0], "install")) {
- if (argc < 2) return usage("install requires an argument");
- if (_use_legacy_install()) {
- return install_app_legacy(transport_type, serial, argc, argv);
- }
- return install_app(transport_type, serial, argc, argv);
- }
- ……
- return 1;
- }
adb会把apk文件copy到data/local/tmp/目录下,然后向shell服务发送pm命令安装apk,最后调用Pm.runInstall()方法来安装apk。
- static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
- static const char *const DATA_DEST = "/data/local/tmp/%s";
- static const char *const SD_DEST = "/sdcard/tmp/%s";
- const char* where = DATA_DEST;
-
- ……
- int result = -1;
- std::vector<const char*> apk_file = {argv[last_apk]};
- std::string apk_dest = android::base::StringPrintf(
- where, android::base::Basename(argv[last_apk]).c_str());
- // 复制app到/data/local/tmp/下
- if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
- argv[last_apk] = apk_dest.c_str();
- //执行pm命令
- result = pm_command(transport, serial, argc, argv);
-
- cleanup_apk:
- delete_file(transport, serial, apk_dest);
- return result;
- }
最后进入到Pm.runInstall()
函数来安装apk。
Pm.java中的runInstall函数:
- private int runInstall() throws RemoteException {
- long startedTime = SystemClock.elapsedRealtime();
- final InstallParams params = makeInstallParams();
- final String inPath = nextArg();
- if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
- File file = new File(inPath);
- if (file.isFile()) {
- try {
- // 使用PackageParser解析apk包
- ApkLite baseApk = PackageParser.parseApkLite(file, 0);
- PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
- null, null);
- params.sessionParams.setSize(
- PackageHelper.calculateInstalledSize(pkgLite, false,
- params.sessionParams.abiOverride));
- } catch (PackageParserException | IOException e) {
- System.err.println("Error: Failed to parse APK file: " + e);
- return 1;
- }
- } else {
- System.err.println("Error: Can't open non-file: " + inPath);
- return 1;
- }
- }
-
- // 创建Session
- final int sessionId = doCreateSession(params.sessionParams,
- params.installerPackageName, params.userId);
-
- try {
- if (inPath == null && params.sessionParams.sizeBytes == -1) {
- System.err.println("Error: must either specify a package size or an APK file");
- return 1;
- }
-
- // 写入Session
- if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
- false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
- return 1;
- }
-
- // 提交Session
- Pair<String, Integer> status = doCommitSession(sessionId, false /*logSuccess*/);
- if (status.second != PackageInstaller.STATUS_SUCCESS) {
- return 1;
- }
- Log.i(TAG, "Package " + status.first + " installed in " + (SystemClock.elapsedRealtime()
- - startedTime) + " ms");
- System.out.println("Success");
- return 0;
- } finally {
- try {
- mInstaller.abandonSession(sessionId);
- } catch (Exception ignore) {
- }
- }
- }
runInstall主要进行了三件事,创建session、对session进行写操作,最后提交session。
doCreateSession函数调用的是PackageInstallerService的createSession,这个过程主要是为APK安装做好准备工作,例如权限检查、目的临时文件的创建等, 最终创建出PackageInstallerSession对象。
PackageInstallerSession可以看做是”安装APK”这个请求的封装,其中包含了处理这个请求需要的一些信息。实际上PackageInstallerSession不仅是分装请求的对象,其自身还是个服务端。
doCreateSession函数:
- private int doCreateSession(SessionParams params, String installerPackageName, int userId)
- throws RemoteException {
- userId = translateUserId(userId, "runInstallCreate");
- if (userId == UserHandle.USER_ALL) {
- userId = UserHandle.USER_SYSTEM;
- params.installFlags |= PackageManager.INSTALL_ALL_USERS;
- }
-
- final int sessionId = mInstaller.createSession(params, installerPackageName, userId);
- return sessionId;
- }
-
- mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
-
- mInstaller = mPm.getPackageInstaller();
进入PackageManagerService.java类看一下getPackageInstaller函数:
- public IPackageInstaller getPackageInstaller() {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
- return null;
- }
- return mInstallerService;
- }
-
- final PackageInstallerService mInstallerService;
-
- mInstallerService = new PackageInstallerService(context, this);
所以最后获取了PackageInstallerService对象,并执行createSession函数:
- public int createSession(SessionParams params, String installerPackageName, int userId) {
- try {
- return createSessionInternal(params, installerPackageName, userId);
- } catch (IOException e) {
- throw ExceptionUtils.wrap(e);
- }
- }
-
- private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
- throws IOException {
- // 权限检查
- final int callingUid = Binder.getCallingUid();
- mPm.enforceCrossUserPermission(callingUid, userId, true, true, "createSession");
-
- if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
- throw new SecurityException("User restriction prevents installing");
- }
-
- ……
-
- // 获取图标数据
- if (params.appIcon != null) {
- final ActivityManager am = (ActivityManager) mContext.getSystemService(
- Context.ACTIVITY_SERVICE);
- final int iconSize = am.getLauncherLargeIconSize();
- if ((params.appIcon.getWidth() > iconSize * 2)
- || (params.appIcon.getHeight() > iconSize * 2)) {
- params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,
- true);
- }
- }
- ……
-
- final long createdMillis = System.currentTimeMillis();
- //创建文件夹
- File stageDir = null;
- String stageCid = null;
- if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
- final boolean isInstant =
- (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
- stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
- } else {
- stageCid = buildExternalStageCid(sessionId);
- }
-
- // 创建session
- session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
- mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
- params, createdMillis, stageDir, stageCid, false, false);
-
- synchronized (mSessions) {
- mSessions.put(sessionId, session);
- }
-
- mCallbacks.notifySessionCreated(session.sessionId, session.userId);
- writeSessionsAsync();
- return sessionId;
- }
之后开始进入doWriteSession函数:
- private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
- boolean logSuccess) throws RemoteException {
- if (STDIN_PATH.equals(inPath)) {
- inPath = null;
- } else if (inPath != null) {
- final File file = new File(inPath);
- if (file.isFile()) {
- sizeBytes = file.length();
- }
- }
-
- final SessionInfo info = mInstaller.getSessionInfo(sessionId);
-
- PackageInstaller.Session session = null;
- InputStream in = null;
- OutputStream out = null;
- try {
- session = new PackageInstaller.Session(
- mInstaller.openSession(sessionId));
-
- if (inPath != null) {
- in = new FileInputStream(inPath);
- } else {
- in = new SizedInputStream(System.in, sizeBytes);
- }
- out = session.openWrite(splitName, 0, sizeBytes);
-
- int total = 0;
- byte[] buffer = new byte[65536];
- int c;
- while ((c = in.read(buffer)) != -1) {
- total += c;
- out.write(buffer, 0, c);
-
- if (info.sizeBytes > 0) {
- final float fraction = ((float) c / (float) info.sizeBytes);
- session.addProgress(fraction);
- }
- }
- session.fsync(out);
-
- if (logSuccess) {
- System.out.println("Success: streamed " + total + " bytes");
- }
- return PackageInstaller.STATUS_SUCCESS;
- } catch (IOException e) {
- System.err.println("Error: failed to write; " + e.getMessage());
- return PackageInstaller.STATUS_FAILURE;
- } finally {
- IoUtils.closeQuietly(out);
- IoUtils.closeQuietly(in);
- IoUtils.closeQuietly(session);
- }
- }
该函数通过PackageInstallerSession将/data/local/tmp的apk拷贝到终端目录内
最后开始执行doCommitSession函数:
- private Pair<String, Integer> doCommitSession(int sessionId, boolean logSuccess)
- throws RemoteException {
- PackageInstaller.Session session = null;
- try {
- // 获取session
- session = new PackageInstaller.Session(
- mInstaller.openSession(sessionId));
-
- final LocalIntentReceiver receiver = new LocalIntentReceiver();
- // 执行session的commit函数
- session.commit(receiver.getIntentSender());
-
- final Intent result = receiver.getResult();
- final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
- PackageInstaller.STATUS_FAILURE);
- if (status == PackageInstaller.STATUS_SUCCESS) {
- if (logSuccess) {
- System.out.println("Success");
- }
- } else {
- System.err.println("Failure ["
- + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
- }
- return new Pair<>(result.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME), status);
- } finally {
- IoUtils.closeQuietly(session);
- }
- }
跟踪下PackageInstaller.java中的session的commit函数:
- public static class Session implements Closeable {
- private IPackageInstallerSession mSession;
-
- public void commit(@NonNull IntentSender statusReceiver) {
- try {
- mSession.commit(statusReceiver);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- }
执行进入PackageInstallerSession.java类中的commit函数:
- public void commit(IntentSender statusReceiver) {
- Preconditions.checkNotNull(statusReceiver);
-
- final boolean wasSealed;
- synchronized (mLock) {
- wasSealed = mSealed;
- if (!mSealed) {
- for (RevocableFileDescriptor fd : mFds) {
- if (!fd.isRevoked()) {
- throw new SecurityException("Files still open");
- }
- }
- for (FileBridge bridge : mBridges) {
- if (!bridge.isClosed()) {
- throw new SecurityException("Files still open");
- }
- }
- mSealed = true;
- }
- mClientProgress = 1f;
- computeProgressLocked(true);
- }
-
- if (!wasSealed) {
- mCallback.onSessionSealedBlocking(this);
- }
-
- mActiveCount.incrementAndGet();
-
- final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
- statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);
- mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
- }
函数中发送消息MSG_COMMIT:
- private final Handler.Callback mHandlerCallback = new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- final PackageInfo pkgInfo = mPm.getPackageInfo(
- params.appPackageName, PackageManager.GET_SIGNATURES
- | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
- final ApplicationInfo appInfo = mPm.getApplicationInfo(
- params.appPackageName, 0, userId);
-
- synchronized (mLock) {
- if (msg.obj != null) {
- mRemoteObserver = (IPackageInstallObserver2) msg.obj;
- }
-
- try {
- commitLocked(pkgInfo, appInfo);
- } catch (PackageManagerException e) {
- final String completeMsg = ExceptionUtils.getCompleteMessage(e);
- Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
- destroyInternal();
- dispatchSessionFinished(e.error, completeMsg, null);
- }
-
- return true;
- }
- }
- };
之后执行了commitLocked函数:
- private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
- throws PackageManagerException {
- ……
- try {
- resolveStageDir();
- } catch (IOException e) {
- throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
- "Failed to resolve stage location", e);
- }
-
- // 验证app是否正常
- validateInstallLocked(pkgInfo, appInfo);
-
- Preconditions.checkNotNull(mPackageName);
- Preconditions.checkNotNull(mSignatures);
- Preconditions.checkNotNull(mResolvedBaseFile);
-
- if (!mPermissionsAccepted) {
- // 安装权限获得
- final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
- intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
- intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
- try {
- mRemoteObserver.onUserActionRequired(intent);
- } catch (RemoteException ignored) {
- }
-
- close();
- return;
- }
- ……
-
- if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
- try {
- final List<File> fromFiles = mResolvedInheritedFiles;
- final File toDir = resolveStageDir();
-
- if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
- if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
- throw new IllegalStateException("mInheritedFilesBase == null");
- }
-
- if (isLinkPossible(fromFiles, toDir)) {
- if (!mResolvedInstructionSets.isEmpty()) {
- final File oatDir = new File(toDir, "oat");
- // 创建oat文件夹
- createOatDirs(mResolvedInstructionSets, oatDir);
- }
- linkFiles(fromFiles, toDir, mInheritedFilesBase);
- } else {
- copyFiles(fromFiles, toDir);
- }
- } catch (IOException e) {
- throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Failed to inherit existing install", e);
- }
- }
-
- mInternalProgress = 0.5f;
- computeProgressLocked(true);
-
- // 解压native动态库
- extractNativeLibraries(mResolvedStageDir, params.abiOverride);、
- ……
- final UserHandle user;
- if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
- user = UserHandle.ALL;
- } else {
- user = new UserHandle(userId);
- }
-
- mRelinquished = true;
- // 开始真正的安装
- mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
- installerPackageName, installerUid, user, mCertificates);
- }
最后执行了PackageManagerService.java的installStage函数:
- void installStage(String packageName, File stagedDir, String stagedCid,
- IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
- String installerPackageName, int installerUid, UserHandle user,
- Certificate[][] certificates) {
- ……
- final VerificationInfo verificationInfo = new VerificationInfo(
- sessionParams.originatingUri, sessionParams.referrerUri,
- sessionParams.originatingUid, installerUid);
-
- final OriginInfo origin;
- if (stagedDir != null) {
- origin = OriginInfo.fromStagedFile(stagedDir);
- } else {
- origin = OriginInfo.fromStagedContainer(stagedCid);
- }
-
- // 发送INIT_COPY信息
- final Message msg = mHandler.obtainMessage(INIT_COPY);
- final int installReason = fixUpInstallReason(installerPackageName, installerUid,
- sessionParams.installReason);
- final InstallParams params = new InstallParams(origin, null, observer,
- sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
- verificationInfo, user, sessionParams.abiOverride,
- sessionParams.grantedRuntimePermissions, certificates, installReason);
- params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
- msg.obj = params;
-
- Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
- System.identityHashCode(msg.obj));
- Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
- System.identityHashCode(msg.obj));
-
- mHandler.sendMessage(msg);
- }
其中发送了INIT_COPY信息:
- final ArrayList<HandlerParams> mPendingInstalls =
- new ArrayList<HandlerParams>();
-
- case INIT_COPY: {
- // 这里取出的其实就是InstallParams
- HandlerParams params = (HandlerParams) msg.obj;
- //idx为当前等待处理处理的安装请求的个数
- int idx = mPendingInstalls.size();
- if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
- //初始时,mBound的值为false
- if (!mBound) {
- Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
- System.identityHashCode(mHandler));
- //连接安装服务
- if (!connectToService()) {
- ……
- } else {
- //绑定服务成功后,将新的请求加入到mPendingIntalls中,等待处理
- mPendingInstalls.add(idx, params);
- }
- } else {
- //如果是第一个请求,则直接发送事件MCS_BOUND,触发处理流程
- mPendingInstalls.add(idx, params);
- if (idx == 0) {
- mHandler.sendEmptyMessage(MCS_BOUND);
- }
- }
- break;
- }
INIT_COPY最后会发送MCS_BOUND消息触发接下来的流程:
- case MCS_BOUND: {
- if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
- if (msg.obj != null) {
- mContainerService = (IMediaContainerService) msg.obj;
- Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
- System.identityHashCode(mHandler));
- }
- if (mContainerService == null) {
- ……
- } else if (mPendingInstalls.size() > 0) {
- HandlerParams params = mPendingInstalls.get(0);
- if (params != null) {
- ……
- if (params.startCopy()) {
- if (DEBUG_SD_INSTALL) Log.i(TAG,
- "Checking for more work or unbind...");
- // 从读了中删除
- if (mPendingInstalls.size() > 0) {
- mPendingInstalls.remove(0);
- }
- if (mPendingInstalls.size() == 0) {
- ……
- } else {
- if (DEBUG_SD_INSTALL) Log.i(TAG,
- "Posting MCS_BOUND for next work");
- mHandler.sendEmptyMessage(MCS_BOUND);
- }
- }
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- } else {
- Slog.w(TAG, "Empty queue");
- }
- break;
- }
代码中看主要执行了HandlerParams中的startCopy函数,也是在文件PackageManagerService.java中:
- final boolean startCopy() {
- boolean res;
- try {
- if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
-
- if (++mRetries > MAX_RETRIES) {
- Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
- mHandler.sendEmptyMessage(MCS_GIVE_UP);
- handleServiceError();
- return false;
- } else {
- handleStartCopy();
- res = true;
- }
- } catch (RemoteException e) {
- if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
- mHandler.sendEmptyMessage(MCS_RECONNECT);
- res = false;
- }
- handleReturnCode();
- return res;
- }
继`续执行handleStartCopy函数:
- public void handleStartCopy() throws RemoteException {
- int ret = PackageManager.INSTALL_SUCCEEDED;
- // 决定是安装在手机内还是sdcard中,设置对应标志位
- if (origin.staged) {
- if (origin.file != null) {
- installFlags |= PackageManager.INSTALL_INTERNAL;
- installFlags &= ~PackageManager.INSTALL_EXTERNAL;
- } else if (origin.cid != null) {
- installFlags |= PackageManager.INSTALL_EXTERNAL;
- installFlags &= ~PackageManager.INSTALL_INTERNAL;
- } else {
- throw new IllegalStateException("Invalid stage location");
- }
- }
- ……
- // 检查APK的安装位置是否正确
- if (onInt && onSd) {
- // Check if both bits are set.
- Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
- ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
- } else if (onSd && ephemeral) {
- Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
- ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
- } else {
- pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
- packageAbiOverride);
-
- if (DEBUG_EPHEMERAL && ephemeral) {
- Slog.v(TAG, "pkgLite for install: " + pkgLite);
- }
- if (!origin.staged && pkgLite.recommendedInstallLocation
- == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
- final StorageManager storage = StorageManager.from(mContext);
- final long lowThreshold = storage.getStorageLowBytes(
- Environment.getDataDirectory());
-
- final long sizeBytes = mContainerService.calculateInstalledSize(
- origin.resolvedPath, isForwardLocked(), packageAbiOverride);
-
- try {
- mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
- pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
- installFlags, packageAbiOverride);
- } catch (InstallerException e) {
- Slog.w(TAG, "Failed to free cache", e);
- }
- if (pkgLite.recommendedInstallLocation
- == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
- pkgLite.recommendedInstallLocation
- = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
- }
- }
- }
-
- ……
- // createInstallArgs用于创建一个安装参数对象
- final InstallArgs args = createInstallArgs(this);
- mArgs = args;
-
-
- ……
- // 调用InstallArgs的copyApk函数
- ret = args.copyApk(mContainerService, true);
- ……
- mRet = ret;
- }
handleStartCopy主要功能是获取安装位置信息以及复制apk到指定位置。
InstallArgs中的copyApk负责复制APK文件,具体实现在子类FileInstallArgs和MoveInstallArgs里面:
- private InstallArgs createInstallArgs(InstallParams params) {
- if (params.move != null) {
- return new MoveInstallArgs(params);
- } else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
- return new AsecInstallArgs(params);
- } else {
- return new FileInstallArgs(params);
- }
- }
继续看下startCopy中的handleReturnCode函数:
- void handleReturnCode() {
- if (mArgs != null) {
- processPendingInstall(mArgs, mRet);
- }
- }
主要的安装流程都在processPendingInstall函数:
- private void processPendingInstall(final InstallArgs args, final int currentStatus) {
- mHandler.post(new Runnable() {
- public void run() {
- mHandler.removeCallbacks(this);
-
- PackageInstalledInfo res = new PackageInstalledInfo();
- res.setReturnCode(currentStatus);
- res.uid = -1;
- res.pkg = null;
- res.removedInfo = null;
- if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- //1、预安装,检查包状态,确保环境ok,如果环境不ok,那么会清理拷贝的文件
- args.doPreInstall(res.returnCode);
- synchronized (mInstallLock) {
- //2、安装,调用installPackageTracedLI进行安装
- installPackageTracedLI(args, res);
- }
- //3、安装收尾
- args.doPostInstall(res.returnCode, res.uid);
- }
-
- ……
-
- if (!doRestore) {
- // No restore possible, or the Backup Manager was mysteriously not
- // available -- just fire the post-install work request directly.
- if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
-
- Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
- //4、生成一个POST_INSTALL消息给PackageHanlder
- Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
- mHandler.sendMessage(msg);
- }
- }
- });
- }
看一下installPackageTracedLI函数:
- private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
- installPackageLI(args, res);
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
继续跟踪installPackageLI函数:
- private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
- ……
- // PackageParser对象
- PackageParser pp = new PackageParser();
- pp.setSeparateProcesses(mSeparateProcesses);
- pp.setDisplayMetrics(mMetrics);
- pp.setCallback(mPackageParserCallback);
-
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
- final PackageParser.Package pkg;
- try {
- // 开始解析package
- pkg = pp.parsePackage(tmpPackageFile, parseFlags);
- } catch (PackageParserException e) {
- res.setError("Failed parse during installPackageLI", e);
- return;
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
-
- if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
- Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target O");
- res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
- "Instant app package must target O");
- return;
- }
- if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) {
- Slog.w(TAG, "Instant app package " + pkg.packageName
- + " does not target targetSandboxVersion 2");
- res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
- "Instant app package must use targetSanboxVersion 2");
- return;
- }
-
- if (pkg.applicationInfo.isStaticSharedLibrary()) {
- // 静态库
- renameStaticSharedLibraryPackage(pkg);
-
- // No static shared libs on external storage
- if (onExternal) {
- Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
- res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
- "Packages declaring static-shared libs cannot be updated");
- return;
- }
- }
-
-
- try {
- //2. 加载证书,获取签名信息
- if (args.certificates != null) {
- try {
- PackageParser.populateCertificates(pkg, args.certificates);
- } catch (PackageParserException e) {
- PackageParser.collectCertificates(pkg, parseFlags);
- }
- } else {
- PackageParser.collectCertificates(pkg, parseFlags);
- }
- } catch (PackageParserException e) {
- res.setError("Failed collect during installPackageLI", e);
- return;
- }
-
-
- pp = null;
- String oldCodePath = null;
- boolean systemApp = false;
- synchronized (mPackages) {
- // 3.检测packages是否已经存在
- if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
- String oldName = mSettings.getRenamedPackageLPr(pkgName);
- if (pkg.mOriginalPackages != null
- && pkg.mOriginalPackages.contains(oldName)
- && mPackages.containsKey(oldName)) {
- pkg.setPackageName(oldName);
- pkgName = pkg.packageName;
- replace = true;
- if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
- + oldName + " pkgName=" + pkgName);
- } else if (mPackages.containsKey(pkgName)) {
- replace = true;
- if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
- }
- ……
-
- if (replace) {
- // 4.更新已经存在的packages
- PackageParser.Package oldPackage = mPackages.get(pkgName);
- final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion;
- final int newTargetSdk = pkg.applicationInfo.targetSdkVersion;
- if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
- && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
- res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE,
- "Package " + pkg.packageName + " new target SDK " + newTargetSdk
- + " doesn't support runtime permissions but the old"
- + " target SDK " + oldTargetSdk + " does.");
- return;
- }
- final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion;
- final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion;
- if (oldTargetSandbox == 2 && newTargetSandbox != 2) {
- res.setError(PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
- "Package " + pkg.packageName + " new target sandbox "
- + newTargetSandbox + " is incompatible with the previous value of"
- + oldTargetSandbox + ".");
- return;
- }
-
- if (oldPackage.parentPackage != null) {
- res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
- "Package " + pkg.packageName + " is child of package "
- + oldPackage.parentPackage + ". Child packages "
- + "can be updated only through the parent package.");
- return;
- }
- }
- }
- ……
-
- startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);
-
- try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
- "installPackageLI")) {
- if (replace) {
- if (pkg.applicationInfo.isStaticSharedLibrary()) {
- // 4.更新已经存在的packages
- PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
- if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) {
- res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
- + "static-shared libs cannot be updated");
- return;
- }
- }
- replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
- installerPackageName, res, args.installReason);
- } else {
- // 5.安装新的packages
- installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
- args.user, installerPackageName, volumeUuid, res, args.installReason);
- }
- }
- ……
- }
这一段代码比较多,主要解析APK的AndroidManifest.xml,将每个标签对应的信息添加到Package的相关列表中,如将下的信息添加到Package的activities列表等。
- 加载apk证书,获取签名信息
- 检查目前安装的APK是否在系统中已存在:
已存在,则调用replacePackageLIF进行替换安装。
不存在,否则调用installNewPackageLIF进行安装。
继续看一下installNewPackageLIF函数:
- private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
- int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
- PackageInstalledInfo res, int installReason) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
-
- String pkgName = pkg.packageName;
-
- if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
-
- synchronized(mPackages) {
- final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName);
- if (renamedPackage != null) {
- res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
- + " without first uninstalling package running as "
- + renamedPackage);
- return;
- }
- if (mPackages.containsKey(pkgName)) {
- // Don't allow installation over an existing package with the same name.
- res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
- + " without first uninstalling.");
- return;
- }
- }
-
- try {
- // 1. 安装apk
- PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
- System.currentTimeMillis(), user);
-
- // 更新set
- updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
-
- if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- prepareAppDataAfterInstallLIF(newPackage);
-
- } else {
- // Remove package from internal structures, but keep around any
- // data that might have already existed
- deletePackageLIF(pkgName, UserHandle.ALL, false, null,
- PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
- }
- } catch (PackageManagerException e) {
- res.setError("Package couldn't be installed in " + pkg.codePath, e);
- }
-
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
scanPackageTracedL函数最后会安装apk:
- private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
- int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]");
- try {
- return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
继续执行scanPackageLI:
- private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
- int scanFlags, long currentTime, @Nullable UserHandle user)
- throws PackageManagerException {
- boolean success = false;
- try {
- final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
- currentTime, user);
- success = true;
- return res;
- } finally {
- if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
- // DELETE_DATA_ON_FAILURES is only used by frozen paths
- destroyAppDataLIF(pkg, UserHandle.USER_ALL,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
- destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
- }
- }
- }
scanPackageDirtyLI是apk安装的核心部分,下一篇文章继续介绍下。
到这里基本上安装就结束了。接下来看下流程图: