美文网首页Android开发适配安卓
Android应用安装流程(基于Android9.0)

Android应用安装流程(基于Android9.0)

作者: android_coder | 来源:发表于2019-06-06 17:00 被阅读0次

普通应用的安装流程主要是分为下面几步

1:拷贝apk文件到/data/app下面

2:解析apk文件信息

3:dexopt操作

4:更新权限信息

5:完成安装,发送Intent.ACTION_PACKAGE_ADDED广播

1:将APK文件拷贝到/data/app/目录下

我们知道在安装apk的过程中是有一个安装界面的,在我们点击了确定之后才触发相应的操作的,这个界面是安装器的界面,这也是安装的入口

private void startInstall() {
    // Start subactivity to actually install the application
    Intent newIntent = new Intent();
    newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
            mPkgInfo.applicationInfo);
    newIntent.setData(mPackageURI);
    newIntent.setClass(this, InstallInstalling.class);
    String installerPackageName = getIntent().getStringExtra(
            Intent.EXTRA_INSTALLER_PACKAGE_NAME);
    if (mOriginatingURI != null) {
        newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
    }
    if (mReferrerURI != null) {
        newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
    }
    if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
        newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
    }
    if (installerPackageName != null) {
        newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
                installerPackageName);
    }
    if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
        newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
    }
    newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
    if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
    startActivity(newIntent);
    finish();
}

protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.install_installing);

    ApplicationInfo appInfo = getIntent()
            .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
    mPackageURI = getIntent().getData();

    if ("package".equals(mPackageURI.getScheme())) {
        try {
            getPackageManager().installExistingPackage(appInfo.packageName);
            launchSuccess();
        } catch (PackageManager.NameNotFoundException e) {
            launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
        }
    } else {
        final File sourceFile = new File(mPackageURI.getPath());
        PackageUtil.initSnippetForNewApp(this, PackageUtil.getAppSnippet(this, appInfo,
                sourceFile), R.id.app_snippet);

        if (savedInstanceState != null) {
            mSessionId = savedInstanceState.getInt(SESSION_ID);
            mInstallId = savedInstanceState.getInt(INSTALL_ID);

            // Reregister for result; might instantly call back if result was delivered while
            // activity was destroyed
            try {
                InstallEventReceiver.addObserver(this, mInstallId,
                        this::launchFinishBasedOnResult);
            } catch (EventResultPersister.OutOfIdsException e) {
                // Does not happen
            }
        } else {
            PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            params.installFlags = PackageManager.INSTALL_FULL_APP;
            params.referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
            params.originatingUri = getIntent()
                    .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
            params.originatingUid = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
                    UID_UNKNOWN);
            params.installerPackageName =
                    getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);

            File file = new File(mPackageURI.getPath());
            try {
                PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
                params.setAppPackageName(pkg.packageName);
                params.setInstallLocation(pkg.installLocation);
                params.setSize(
                        PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
            } catch (PackageParser.PackageParserException e) {
                Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");
                Log.e(LOG_TAG,
                        "Cannot calculate installed size " + file + ". Try only apk size.");
                params.setSize(file.length());
            } catch (IOException e) {
                Log.e(LOG_TAG,
                        "Cannot calculate installed size " + file + ". Try only apk size.");
                params.setSize(file.length());
            }

            try {
                mInstallId = InstallEventReceiver
                        .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
                                this::launchFinishBasedOnResult);
            } catch (EventResultPersister.OutOfIdsException e) {
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }

            try {
                mSessionId = getPackageManager().getPackageInstaller().createSession(params);--->创建一个会话
            } catch (IOException e) {
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }
        }

        mCancelButton = (Button) findViewById(R.id.cancel_button);

        mCancelButton.setOnClickListener(view -> {
            if (mInstallingTask != null) {
                mInstallingTask.cancel(true);
            }

            if (mSessionId > 0) {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);
                mSessionId = 0;
            }

            setResult(RESULT_CANCELED);
            finish();
        });

        mSessionCallback = new InstallSessionCallback();
    }
}

进入到PackageInstaller的createSession

public int createSession(@NonNull SessionParams params) throws IOException {
    try {
        final String installerPackage;
        if (params.installerPackageName == null) {
            installerPackage = mInstallerPackageName;
        } else {
            installerPackage = params.installerPackageName;
        }
        // mInstaller对象是IPackageInstaller类型的对象,对应的是PackageInstallerService
        return mInstaller.createSession(params, installerPackage, mUserId);
    } catch (RuntimeException e) {
        ExceptionUtils.maybeUnwrapIOException(e);
        throw e;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

进入到PackageInstallerService的createSession方法

@Override
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 {
    ...........................................
    } else {
        // Only apps with INSTALL_PACKAGES are allowed to set an installer that is not the
        // caller.
        if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES) !=
                PackageManager.PERMISSION_GRANTED) {
            mAppOps.checkPackage(callingUid, installerPackageName);
        }

        params.installFlags &= ~PackageManager.INSTALL_FROM_ADB;-------------->不是adb的方式安装
        params.installFlags &= ~PackageManager.INSTALL_ALL_USERS;------------->不是安装到所有的用户下面
        params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;------->替换已经存在的package
        if ((params.installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0
                && !mPm.isCallerVerifier(callingUid)) {
            params.installFlags &= ~PackageManager.INSTALL_VIRTUAL_PRELOAD;
        }
    }

    // Only system components can circumvent runtime permissions when installing.
    if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
            && mContext.checkCallingOrSelfPermission(Manifest.permission
            .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
        throw new SecurityException("You need the "
                + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
                + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
    }
    .........................................
    switch (params.mode) {
        case SessionParams.MODE_FULL_INSTALL:
        case SessionParams.MODE_INHERIT_EXISTING:
            break;
        default:
            throw new IllegalArgumentException("Invalid install mode: " + params.mode);
    }
    ........................................
    final int sessionId;
    final PackageInstallerSession session;
    synchronized (mSessions) {
        // Sanity check that installer isn't going crazy
        final int activeCount = getSessionCount(mSessions, callingUid);
        if (activeCount >= MAX_ACTIVE_SESSIONS) {
            throw new IllegalStateException(
                    "Too many active sessions for UID " + callingUid);
        }
        final int historicalCount = mHistoricalSessionsByInstaller.get(callingUid);
        if (historicalCount >= MAX_HISTORICAL_SESSIONS) {
            throw new IllegalStateException(
                    "Too many historical sessions for UID " + callingUid);
        }

        sessionId = allocateSessionIdLocked();------------------->分配一个会话id
    }

    final long createdMillis = System.currentTimeMillis();
    // We're staging to exactly one location
    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 = 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;
}

上面主要是创建一个会话id的

InstallInstalling的onResume方法

@Override
protected void onResume() {
    super.onResume();

    // This is the first onResume in a single life of the activity
    if (mInstallingTask == null) {
        PackageInstaller installer = getPackageManager().getPackageInstaller();
        PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);

        if (sessionInfo != null && !sessionInfo.isActive()) {
            mInstallingTask = new InstallingAsyncTask();--------->创建一个AsyncTask
            mInstallingTask.execute();
        } else {
            // we will receive a broadcast when the install is finished
            mCancelButton.setEnabled(false);
            setFinishOnTouchOutside(false);
        }
    }
}

protected PackageInstaller.Session doInBackground(Void... params) {
        PackageInstaller.Session session;
        try {
            session = getPackageManager().getPackageInstaller().openSession(mSessionId);
        } catch (IOException e) {
            return null;
        }

        session.setStagingProgress(0);

        try {
            File file = new File(mPackageURI.getPath());

            try (InputStream in = new FileInputStream(file)) {
                long sizeBytes = file.length();
                try (OutputStream out = session
                        .openWrite("PackageInstaller", 0, sizeBytes)) {
                    byte[] buffer = new byte[1024 * 1024];
                    while (true) {
                        int numRead = in.read(buffer);

                        if (numRead == -1) {
                            session.fsync(out);
                            break;
                        }

                        if (isCancelled()) {
                            session.close();
                            break;
                        }

                        out.write(buffer, 0, numRead);
                        if (sizeBytes > 0) {
                            float fraction = ((float) numRead / (float) sizeBytes);
                            session.addProgress(fraction);
                        }
                    }
                }
            }

            return session;
        } catch (IOException | SecurityException e) {
            Log.e(LOG_TAG, "Could not write package", e);

            session.close();

            return null;
        } finally {
            synchronized (this) {
                isDone = true;
                notifyAll();
            }
        }
    }

    @Override
    protected void onPostExecute(PackageInstaller.Session session) {
        if (session != null) {
            Intent broadcastIntent = new Intent(BROADCAST_ACTION);
            broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            broadcastIntent.setPackage(
                    getPackageManager().getPermissionControllerPackageName());
            broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);

            PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    InstallInstalling.this,
                    mInstallId,
                    broadcastIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);

            session.commit(pendingIntent.getIntentSender());
            mCancelButton.setEnabled(false);
            setFinishOnTouchOutside(false);
        } else {
            getPackageManager().getPackageInstaller().abandonSession(mSessionId);

            if (!isCancelled()) {
                launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
            }
        }
    }

1:doInBackground主要是完成文件的拷贝工作

2:onPostExecute主要是调用commit方法提交会话

public void commit(@NonNull IntentSender statusReceiver) {
        try {
            mSession.commit(statusReceiver, false);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
}

PackageInstallerSession.java

public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
    Preconditions.checkNotNull(statusReceiver);

    final boolean wasSealed;
    synchronized (mLock) {
        assertCallerIsOwnerOrRootLocked();
        assertPreparedAndNotDestroyedLocked("commit");

        final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
                mContext, statusReceiver, sessionId,
                isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
        mRemoteObserver = adapter.getBinder();

        if (forTransfer) {
            mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);

            if (mInstallerUid == mOriginalInstallerUid) {
                throw new IllegalArgumentException("Session has not been transferred");
            }
        } else {
            if (mInstallerUid != mOriginalInstallerUid) {
                throw new IllegalArgumentException("Session has been transferred");
            }
        }

        wasSealed = mSealed;
        if (!mSealed) {
            try {
                sealAndValidateLocked();
            } catch (IOException e) {
                throw new IllegalArgumentException(e);
            } catch (PackageManagerException e) {
                // Do now throw an exception here to stay compatible with O and older
                destroyInternal();
                dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
                return;
            }
        }

        // Client staging is fully done at this point
        mClientProgress = 1f;
        computeProgressLocked(true);

        // This ongoing commit should keep session active, even though client
        // will probably close their end.
        mActiveCount.incrementAndGet();

        mCommitted = true;
        mHandler.obtainMessage(MSG_COMMIT).sendToTarget();------>发送一个消息
    }

    if (!wasSealed) {
        // Persist the fact that we've sealed ourselves to prevent
        // mutations of any hard links we create. We do this without holding
        // the session lock, since otherwise it's a lock inversion.
        mCallback.onSessionSealedBlocking(this);
    }
}

case MSG_COMMIT:
  synchronized (mLock) {
          try {
               commitLocked();
             } catch (PackageManagerException e) {
               final String completeMsg = ExceptionUtils.getCompleteMessage(e);
                Slog.e(TAG,
                       "Commit of session " + sessionId + " failed: " + completeMsg);
                 destroyInternal();
                 dispatchSessionFinished(e.error, completeMsg, null);
              }
          }

break;
commitLocked

private void commitLocked()
        throws PackageManagerException {
    if (mDestroyed) {
        throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
    }
    if (!mSealed) {
        throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
    }

    Preconditions.checkNotNull(mPackageName);
    Preconditions.checkNotNull(mSigningDetails);
    Preconditions.checkNotNull(mResolvedBaseFile);

    if (needToAskForPermissionsLocked()) {
        // User needs to accept permissions; give installer an intent they
        // can use to involve user.
        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) {
        }

        // Commit was keeping session marked as active until now; release
        // that extra refcount so session appears idle.
        closeInternal(false);
        return;
    }

    // Inherit any packages and native libraries from existing install that
    // haven't been overridden.
    if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
        try {
            final List<File> fromFiles = mResolvedInheritedFiles;
            final File toDir = resolveStageDirLocked();

            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");
                    createOatDirs(mResolvedInstructionSets, oatDir);
                }
                // pre-create lib dirs for linking if necessary
                if (!mResolvedNativeLibPaths.isEmpty()) {
                    for (String libPath : mResolvedNativeLibPaths) {
                        // "/lib/arm64" -> ["lib", "arm64"]
                        final int splitIndex = libPath.lastIndexOf('/');
                        if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
                            Slog.e(TAG, "Skipping native library creation for linking due to "
                                    + "invalid path: " + libPath);
                            continue;
                        }
                        final String libDirPath = libPath.substring(1, splitIndex);
                        final File libDir = new File(toDir, libDirPath);
                        if (!libDir.exists()) {
                            NativeLibraryHelper.createNativeLibrarySubdir(libDir);
                        }
                        final String archDirPath = libPath.substring(splitIndex + 1);
                        NativeLibraryHelper.createNativeLibrarySubdir(
                                new File(libDir, archDirPath));
                    }
                }
                linkFiles(fromFiles, toDir, mInheritedFilesBase);
            } else {
                // TODO: this should delegate to DCS so the system process
                // avoids holding open FDs into containers.
                copyFiles(fromFiles, toDir);
            }
        } catch (IOException e) {
            throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                    "Failed to inherit existing install", e);
        }
    }

    // TODO: surface more granular state from dexopt
    mInternalProgress = 0.5f;
    computeProgressLocked(true);

    // Unpack native libraries
    extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());

    // We've reached point of no return; call into PMS to install the stage.
    // Regardless of success or failure we always destroy session.
    final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
        @Override
        public void onUserActionRequired(Intent intent) {
            throw new IllegalStateException();
        }

        @Override
        public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                Bundle extras) {
            destroyInternal();
            dispatchSessionFinished(returnCode, msg, extras);
        }
    };

    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, localObserver, params,
            mInstallerPackageName, mInstallerUid, user, mSigningDetails);
}

1:创建对应的目录

2:installStage,主要是发送一个INIT_COPY

case INIT_COPY: {
     HandlerParams params = (HandlerParams) msg.obj;
     int idx = mPendingInstalls.size();
     if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
                // If a bind was already initiated we dont really
                // need to do anything. The pending install
                // will be processed later on.
                if (!mBound) {
                    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                            System.identityHashCode(mHandler));
                    // If this is the only one pending we might
                    // have to bind to the service again.
                    if (!connectToService()) {
                        Slog.e(TAG, "Failed to bind to media container service");
                        params.serviceError();
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                        if (params.traceMethod != null) {
                            Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, params.traceMethod,
                                    params.traceCookie);
                        }
                        return;
                    } else {
                        // Once we bind to the service, the first
                        // pending request will be processed.
                        mPendingInstalls.add(idx, params);
                    }
                } else {
                    mPendingInstalls.add(idx, params);
                    // Already bound to the service. Just make
                    // sure we trigger off processing the first request.
                    if (idx == 0) {
                        mHandler.sendEmptyMessage(MCS_BOUND);
                    }
                }
                break;
}
........................................
} else if (mPendingInstalls.size() > 0) {
                    HandlerParams params = mPendingInstalls.get(0);
                    if (params != null) {
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                                System.identityHashCode(params));
                        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
                        if (params.startCopy()) {
                            // We are done...  look for more work or to
                            // go idle.
                            if (DEBUG_SD_INSTALL) Log.i(TAG,
                                    "Checking for more work or unbind...");
                            // Delete pending install
                            if (mPendingInstalls.size() > 0) {
                                mPendingInstalls.remove(0);
                            }
                            if (mPendingInstalls.size() == 0) {
                                if (mBound) {
                                    if (DEBUG_SD_INSTALL) Log.i(TAG,
                                            "Posting delayed MCS_UNBIND");
                                    removeMessages(MCS_UNBIND);
                                    Message ubmsg = obtainMessage(MCS_UNBIND);
                                    // Unbind after a little delay, to avoid
                                    // continual thrashing.
                                    sendMessageDelayed(ubmsg, 10000);
                                }
                            } else {
                                // There are more pending requests in queue.
                                // Just post MCS_BOUND message to trigger processing
                                // of next pending install.
                                if (DEBUG_SD_INSTALL) Log.i(TAG,
                                        "Posting MCS_BOUND for next work");
                                mHandler.sendEmptyMessage(MCS_BOUND);
                            }
                        }
                        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                    }
                } else {
                    // Should never happen ideally.
                    Slog.w(TAG, "Empty queue");
                }
  break;
  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;
    }

public void handleStartCopy() throws RemoteException {
        int ret = PackageManager.INSTALL_SUCCEEDED;
        .......................
        final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;----->安装到sdcard
        final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;---->内置存储
        final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
        PackageInfoLite pkgLite = null;
        .................................
        //安装路径检查
        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_INSTANT && ephemeral) {
                Slog.v(TAG, "pkgLite for install: " + pkgLite);
            }

            /*
             * If we have too little free space, try to free cache
             * before giving up.
             */
            if (!origin.staged && pkgLite.recommendedInstallLocation
                    == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                // TODO: focus freeing disk space on the target device
                final StorageManager storage = StorageManager.from(mContext);
                final long lowThreshold = storage.getStorageLowBytes(
                        Environment.getDataDirectory());

                final long sizeBytes = mContainerService.calculateInstalledSize(
                        origin.resolvedPath, 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);
                }

                /*
                 * The cache free must have deleted the file we
                 * downloaded to install.
                 *
                 * TODO: fix the "freeCache" call to not delete
                 *       the file we care about.
                 */
                if (pkgLite.recommendedInstallLocation
                        == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
                    pkgLite.recommendedInstallLocation
                        = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
                }
            }
        }

        if (ret == PackageManager.INSTALL_SUCCEEDED) {
            int loc = pkgLite.recommendedInstallLocation;
            if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
                ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
            } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
                ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
            } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
            } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
                ret = PackageManager.INSTALL_FAILED_INVALID_APK;
            } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
                ret = PackageManager.INSTALL_FAILED_INVALID_URI;
            } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
                ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
            } else {
                // Override with defaults if needed.
                loc = installLocationPolicy(pkgLite);
                if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
                    ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
                } else if (!onSd && !onInt) {
                    // Override install location with flags
                    if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
                        // Set the flag to install on external media.
                        installFlags |= PackageManager.INSTALL_EXTERNAL;
                        installFlags &= ~PackageManager.INSTALL_INTERNAL;
                    } else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {
                        if (DEBUG_INSTANT) {
                            Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
                        }
                        installFlags |= PackageManager.INSTALL_INSTANT_APP;
                        installFlags &= ~(PackageManager.INSTALL_EXTERNAL
                                |PackageManager.INSTALL_INTERNAL);
                    } else {
                        // Make sure the flag for installing on external
                        // media is unset
                        installFlags |= PackageManager.INSTALL_INTERNAL;
                        installFlags &= ~PackageManager.INSTALL_EXTERNAL;
                    }
                }
            }
        }

        final InstallArgs args = createInstallArgs(this);
        mArgs = args;

        if (ret == PackageManager.INSTALL_SUCCEEDED) {
            // TODO: http://b/22976637
            // Apps installed for "all" users use the device owner to verify the app
            UserHandle verifierUser = getUser();
            if (verifierUser == UserHandle.ALL) {
                verifierUser = UserHandle.SYSTEM;
            }

            /*
             * Determine if we have any installed package verifiers. If we
             * do, then we'll defer to them to verify the packages.
             */
            final int requiredUid = mRequiredVerifierPackage == null ? -1
                    : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
                            verifierUser.getIdentifier());
            final int installerUid =
                    verificationInfo == null ? -1 : verificationInfo.installerUid;
            if (!origin.existing && requiredUid != -1
                    && isVerificationEnabled(
                            verifierUser.getIdentifier(), installFlags, installerUid)) {
                final Intent verification = new Intent(
                        Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
                verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
                        PACKAGE_MIME_TYPE);
                verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                // Query all live verifiers based on current user state
                final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
                        PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
                        false /*allowDynamicSplits*/);

                if (DEBUG_VERIFY) {
                    Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
                            + verification.toString() + " with " + pkgLite.verifiers.length
                            + " optional verifiers");
                }

                final int verificationId = mPendingVerificationToken++;

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
                        installerPackageName);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
                        installFlags);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
                        pkgLite.packageName);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
                        pkgLite.versionCode);

                verification.putExtra(PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
                        pkgLite.getLongVersionCode());

                if (verificationInfo != null) {
                    if (verificationInfo.originatingUri != null) {
                        verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
                                verificationInfo.originatingUri);
                    }
                    if (verificationInfo.referrer != null) {
                        verification.putExtra(Intent.EXTRA_REFERRER,
                                verificationInfo.referrer);
                    }
                    if (verificationInfo.originatingUid >= 0) {
                        verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
                                verificationInfo.originatingUid);
                    }
                    if (verificationInfo.installerUid >= 0) {
                        verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
                                verificationInfo.installerUid);
                    }
                }

                final PackageVerificationState verificationState = new PackageVerificationState(
                        requiredUid, args);

                mPendingVerification.append(verificationId, verificationState);

                final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
                        receivers, verificationState);

                DeviceIdleController.LocalService idleController = getDeviceIdleController();
                final long idleDuration = getVerificationTimeout();

                /*
                 * If any sufficient verifiers were listed in the package
                 * manifest, attempt to ask them.
                 */
                if (sufficientVerifiers != null) {
                    final int N = sufficientVerifiers.size();
                    if (N == 0) {
                        Slog.i(TAG, "Additional verifiers required, but none installed.");
                        ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
                    } else {
                        for (int i = 0; i < N; i++) {
                            final ComponentName verifierComponent = sufficientVerifiers.get(i);
                            idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                                    verifierComponent.getPackageName(), idleDuration,
                                    verifierUser.getIdentifier(), false, "package verifier");

                            final Intent sufficientIntent = new Intent(verification);
                            sufficientIntent.setComponent(verifierComponent);
                            mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
                        }
                    }
                }

                final ComponentName requiredVerifierComponent = matchComponentForVerifier(
                        mRequiredVerifierPackage, receivers);
                //是否需要校验
                if (ret == PackageManager.INSTALL_SUCCEEDED
                        && mRequiredVerifierPackage != null) {
                    Trace.asyncTraceBegin(
                            TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
                    /*
                     * Send the intent to the required verification agent,
                     * but only start the verification timeout after the
                     * target BroadcastReceivers have run.
                     */
                    verification.setComponent(requiredVerifierComponent);
                    idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                            mRequiredVerifierPackage, idleDuration,
                            verifierUser.getIdentifier(), false, "package verifier");
                    mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
                            android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
                            new BroadcastReceiver() {
                                @Override
                                public void onReceive(Context context, Intent intent) {
                                    final Message msg = mHandler
                                            .obtainMessage(CHECK_PENDING_VERIFICATION);
                                    msg.arg1 = verificationId;
                                    mHandler.sendMessageDelayed(msg, getVerificationTimeout());
                                }
                            }, null, 0, null, null);

                    /*
                     * We don't want the copy to proceed until verification
                     * succeeds, so null out this field.
                     */
                    mArgs = null;
                }
            } else {
                /*
                 * No package verification is enabled, so immediately start
                 * the remote call to initiate copy using temporary file.
                 */
                ret = args.copyApk(mContainerService, true);//开始拷贝
            }
        }

        mRet = ret;
    }

int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
        try {
            return doCopyApk(imcs, temp);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
}

private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
       ......................................
        try {
            final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
            final File tempDir =
                    mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
            codeFile = tempDir;
            resourceFile = tempDir;
        } catch (IOException e) {
            Slog.w(TAG, "Failed to create copy file: " + e);
            return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
        }

        final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
            @Override
            public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
                if (!FileUtils.isValidExtFilename(name)) {
                    throw new IllegalArgumentException("Invalid filename: " + name);
                }
                try {
                    final File file = new File(codeFile, name);-------------->创建文件目录
                    final FileDescriptor fd = Os.open(file.getAbsolutePath(),
                            O_RDWR | O_CREAT, 0644);
                    Os.chmod(file.getAbsolutePath(), 0644);
                    return new ParcelFileDescriptor(fd);
                } catch (ErrnoException e) {
                    throw new RemoteException("Failed to open: " + e.getMessage());
                }
            }
        };

        int ret = PackageManager.INSTALL_SUCCEEDED;
        ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
        if (ret != PackageManager.INSTALL_SUCCEEDED) {
            Slog.e(TAG, "Failed to copy package");
            return ret;
        }

        final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
        NativeLibraryHelper.Handle handle = null;
        try {
            handle = NativeLibraryHelper.Handle.create(codeFile);
            ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
                    abiOverride);-------------------------->copy so 文件
        } catch (IOException e) {
            Slog.e(TAG, "Copying native libraries failed", e);
            ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
        } finally {
            IoUtils.closeQuietly(handle);
        }

        return ret;
    }

public int copyPackage(String packagePath, IParcelFileDescriptorFactory target) {
        if (packagePath == null || target == null) {
            return PackageManager.INSTALL_FAILED_INVALID_URI;
        }

        PackageLite pkg = null;
        try {
            final File packageFile = new File(packagePath);
            pkg = PackageParser.parsePackageLite(packageFile, 0);----------------->解析出一个最小的packageLite
            return copyPackageInner(pkg, target);
        } catch (PackageParserException | IOException | RemoteException e) {
            Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);
            return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
        }
}

private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)
        throws IOException, RemoteException {
    copyFile(pkg.baseCodePath, target, "base.apk");--------------->文件名是base.apk
    if (!ArrayUtils.isEmpty(pkg.splitNames)) {
        for (int i = 0; i < pkg.splitNames.length; i++) {
            copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk");
        }
    }

    return PackageManager.INSTALL_SUCCEEDED;
}

private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName)
        throws IOException, RemoteException {
    Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
    InputStream in = null;
    OutputStream out = null;
    try {
        in = new FileInputStream(sourcePath);
        out = new ParcelFileDescriptor.AutoCloseOutputStream(
                target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE));
        FileUtils.copy(in, out);
    } finally {
        IoUtils.closeQuietly(out);
        IoUtils.closeQuietly(in);
    }
}

在startCopy执行完成之后,会继续调用handleReturnCode,如果拷贝完成之后,会解析apk的信息
handleReturnCode主要就是解析apk的信息

2:handleReturnCode解析apk信息

void handleReturnCode() {
        // If mArgs is null, then MCS couldn't be reached. When it
        // reconnects, it will try again to install. At that point, this
        // will succeed.
        if (mArgs != null) {
            processPendingInstall(mArgs, mRet);
        }
}

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
    // Queue up an async operation since the package installation may take a little while.
    mHandler.post(new Runnable() {
        public void run() {
            mHandler.removeCallbacks(this);
             // Result object to be returned
            PackageInstalledInfo res = new PackageInstalledInfo();
            res.setReturnCode(currentStatus);
            res.uid = -1;
            res.pkg = null;
            res.removedInfo = null;
            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                args.doPreInstall(res.returnCode);
                synchronized (mInstallLock) {
                    installPackageTracedLI(args, res);
                }
                args.doPostInstall(res.returnCode, res.uid);
            }

            // A restore should be performed at this point if (a) the install
            // succeeded, (b) the operation is not an update, and (c) the new
            // package has not opted out of backup participation.
            final boolean update = res.removedInfo != null
                    && res.removedInfo.removedPackage != null;
            final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
            boolean doRestore = !update
                    && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);

            // Set up the post-install work request bookkeeping.  This will be used
            // and cleaned up by the post-install event handling regardless of whether
            // there's a restore pass performed.  Token values are >= 1.
            int token;
            if (mNextInstallToken < 0) mNextInstallToken = 1;
            token = mNextInstallToken++;

            PostInstallData data = new PostInstallData(args, res);
            mRunningInstalls.put(token, data);
            if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);

            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
                // Pass responsibility to the Backup Manager.  It will perform a
                // restore if appropriate, then pass responsibility back to the
                // Package Manager to run the post-install observer callbacks
                // and broadcasts.
                IBackupManager bm = IBackupManager.Stub.asInterface(
                        ServiceManager.getService(Context.BACKUP_SERVICE));
                if (bm != null) {
                    if (DEBUG_INSTALL) Log.v(TAG, "token " + token
                            + " to BM for possible restore");
                    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
                    try {
                        // TODO: http://b/22388012
                        if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
                            bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
                        } else {
                            doRestore = false;
                        }
                    } catch (RemoteException e) {
                        // can't happen; the backup manager is local
                    } catch (Exception e) {
                        Slog.e(TAG, "Exception trying to enqueue restore", e);
                        doRestore = false;
                    }
                } else {
                    Slog.e(TAG, "Backup Manager not found!");
                    doRestore = false;
                }
            }

            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);

                Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
                mHandler.sendMessage(msg);
            }
        }
    });
}
2.1installPackageTracedLI(args, res);主要是用来解析apk信息的
 .....................................
 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 {
        pkg = pp.parsePackage(tmpPackageFile, parseFlags);-------解析apk构造出一个package对象,也就是包信息
        DexMetadataHelper.validatePackageDexMetadata(pkg);
 } catch (PackageParserException e) {
        res.setError("Failed parse during installPackageLI", e);
        return;
 } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 }
 ....................................

3:dexopt优化

dexopt优化的条件
final boolean performDexopt = (res.returnCode == PackageManager.INSTALL_SUCCEEDED)
            && !forwardLocked
            && !pkg.applicationInfo.isExternalAsec()
            && (!instantApp || Global.getInt(mContext.getContentResolver(),
            Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
            && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);

    if (performDexopt) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
        // Do not run PackageDexOptimizer through the local performDexOpt
        // method because `pkg` may not be in `mPackages` yet.
        //
        // Also, don't fail application installs if the dexopt step fails.
        DexoptOptions dexoptOptions = new DexoptOptions(pkg.packageName,
                REASON_INSTALL,
                DexoptOptions.DEXOPT_BOOT_COMPLETE |
                DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
        mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
                null /* instructionSets */,
                getOrCreateCompilerPackageStats(pkg),
                mDexManager.getPackageUseInfoOrDefault(pkg.packageName),
                dexoptOptions);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
3.1POST_INSTALL消息的处理
if (data != null) {
     InstallArgs args = data.args;
     PackageInstalledInfo parentRes = data.res;
     final boolean grantPermissions = (args.installFlags
                            & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
     final boolean killApp = (args.installFlags
                            & PackageManager.INSTALL_DONT_KILL_APP) == 0;
     final boolean virtualPreload = ((args.installFlags
                            & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
     final String[] grantedPermissions = args.installGrantPermissions;

     // Handle the parent package
     handlePackagePostInstall(parentRes, grantPermissions, killApp,
                            virtualPreload, grantedPermissions, didRestore,
                            args.installerPackageName, args.observer);

     // Handle the child packages
     final int childCount = (parentRes.addedChildPackages != null)
                            ? parentRes.addedChildPackages.size() : 0;
     for (int i = 0; i < childCount; i++) {
          PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
           handlePackagePostInstall(childRes, grantPermissions, killApp,
           virtualPreload, grantedPermissions, false /*didRestore*/,
           args.installerPackageName, args.observer);
      }

      // Log tracing if needed
      if (args.traceMethod != null) {
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod,
                                args.traceCookie);
       }
      } else {
                    Slog.e(TAG, "Bogus post-install token " + msg.arg1);
     }
     Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1);

handlePackagePostInstall逻辑处理:这个方法主要也是分为两部分

4:更新权限信息

if (grantPermissions) {
            final int callingUid = Binder.getCallingUid();
            mPermissionManager.grantRequestedRuntimePermissions(
                    res.pkg, res.newUsers, grantedPermissions, callingUid,
                    mPermissionCallback);
}

private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
        String[] grantedPermissions, int callingUid, PermissionCallback callback) {
    PackageSetting ps = (PackageSetting) pkg.mExtras;
    if (ps == null) {
        return;
    }

    PermissionsState permissionsState = ps.getPermissionsState();

    final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
            | PackageManager.FLAG_PERMISSION_POLICY_FIXED;

    final boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
            >= Build.VERSION_CODES.M;

    final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.packageName, userId);

    for (String permission : pkg.requestedPermissions) {
        final BasePermission bp;
        synchronized (mLock) {
            bp = mSettings.getPermissionLocked(permission);
        }
        if (bp != null && (bp.isRuntime() || bp.isDevelopment())
                && (!instantApp || bp.isInstant())
                && (supportsRuntimePermissions || !bp.isRuntimeOnly())
                && (grantedPermissions == null
                       || ArrayUtils.contains(grantedPermissions, permission))) {
            final int flags = permissionsState.getPermissionFlags(permission, userId);
            if (supportsRuntimePermissions) {
                // Installer cannot change immutable permissions.
                if ((flags & immutableFlags) == 0) {
                    grantRuntimePermission(permission, pkg.packageName, false, callingUid,
                            userId, callback);
                }
            } else if (mSettings.mPermissionReviewRequired) {
                // In permission review mode we clear the review flag when we
                // are asked to install the app with all permissions granted.
                if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
                    updatePermissionFlags(permission, pkg.packageName,
                            PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
                            userId, callback);
                }
            }
        }
    }
}

5:发送安装完成的广播/应用替换广播

// Send added for users that see the package for the first time
// sendPackageAddedForNewUsers also deals with system apps
 int appId = UserHandle.getAppId(res.uid);
 boolean isSystem = res.pkg.applicationInfo.isSystemApp();
 sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload,
      virtualPreload /*startReceiver*/, appId, firstUserIds, firstInstantUserIds);

public void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted,
        boolean includeStopped, int appId, int[] userIds, int[] instantUserIds) {
    if (ArrayUtils.isEmpty(userIds) && ArrayUtils.isEmpty(instantUserIds)) {
        return;
    }
    Bundle extras = new Bundle(1);
    // Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast
    final int uid = UserHandle.getUid(
            (ArrayUtils.isEmpty(userIds) ? instantUserIds[0] : userIds[0]), appId);
    extras.putInt(Intent.EXTRA_UID, uid);

    sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
            packageName, extras, 0, null, null, userIds, instantUserIds);
    if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) {
        mHandler.post(() -> {
                    for (int userId : userIds) {
                        sendBootCompletedBroadcastToSystemApp(
                                packageName, includeStopped, userId);
                    }
                }
        );
    }
}

总结:一般应用的安装流程,主要分为五个阶段

1:安装器点击确定之后发起安装:startInstall,这个阶段主要是请求拷贝apk文件和so文件

2:拷贝完成之后解析apk的信息,构造一个package信息

3:根据dexopt优化的条件判断是否需要执行dexopt操作

4:更新权限信息

5:发送安装完成/替换的广播

相关文章

网友评论

    本文标题:Android应用安装流程(基于Android9.0)

    本文链接:https://www.haomeiwen.com/subject/umpuxctx.html