1、在PackageInstallerActivity调用startInstallConfirm方法初始化安装确认界面后,这个安装确认界面就会呈现给用户,用户如果想要安装这个应用程序就会点击确定按钮,就会调用PackageInstallerActivity的onClick方法:

packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java

public class PackageInstallerActivity extends OverlayTouchActivity implements OnClickListener {
  	...
    public void onClick(View v) {
        if (v == mOk) {
            if (mOk.isEnabled()) {
                if (mOkCanInstall || mScrollView == null) {
                    if (mSessionId != -1) {
                        mInstaller.setPermissionsResult(mSessionId, true);
                        finish();
                    } else {
                    	//注释0101,用户点击确定按钮
                        startInstall();
                    }
                } else {
                    mScrollView.pageScroll(View.FOCUS_DOWN);
                }
            }
        } else if (v == mCancel) {
            // Cancel and finish
            setResult(RESULT_CANCELED);
            if (mSessionId != -1) {
                mInstaller.setPermissionsResult(mSessionId, false);
            }
            finish();
        }
    }
	
	//startInstall方法用于跳转到InstallInstalling这个Activity,并关闭掉当前的PackageInstallerActivity
    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();
    }
	...
}

2、在onClick方法中分别对确定和取消按钮做处理,用户点击确定按钮,会触发【注释0101】处的startInstall方法,startInstall方法用于跳转到InstallInstalling这个Activity,并关闭掉当前的PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调。 InstallInstalling的onCreate方法如下所示:

packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

public class InstallInstalling extends Activity {
   	...
    @Override
    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 {
        	//根据mPackageURI创建一个对应的File 
            final File sourceFile = new File(mPackageURI.getPath());
            PackageUtil.initSnippetForNewApp(this, PackageUtil.getAppSnippet(this, appInfo,
                    sourceFile), R.id.app_snippet);
			//注释0201 如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId       
            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
                //向InstallEventReceiver注册一个观察者
                try {
                	//注释0202 注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调,无论安装成功或者失败都会关闭当前Activity
                    InstallEventReceiver.addObserver(this, mInstallId,
                            this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    // Does not happen
                }
            } else {
            	//注释0203
                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);
				//注释0204
                File file = new File(mPackageURI.getPath());
                try {
                	//注释0205
                    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 {
                	//注释0206
                    mInstallId = InstallEventReceiver
                            .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
                                    this::launchFinishBasedOnResult);
                } catch (EventResultPersister.OutOfIdsException e) {
                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
                }

                try {
                	//注释0207
                    mSessionId = getPackageManager().getPackageInstaller().createSession(params);
                } catch (IOException e) {
                    launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
                }
            }
			...
            mSessionCallback = new InstallSessionCallback();
        }
    }
    ...
    @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();
            //注释0208 根据mSessionId得到SessionInfo,SessionInfo代表安装会话的详细信息
            PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
			//注释0209 InstallingAsyncTask的doInBackground方法中会根据包(APK)的Uri,将APK的信息通过IO流的形式写入到PackageInstaller.Session中
            if (sessionInfo != null && !sessionInfo.isActive()) {
                mInstallingTask = new InstallingAsyncTask();
                mInstallingTask.execute();
            } else {
                // we will receive a broadcast when the install is finished
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            }
        }
    }
    
	...
	//内部类
	 private final class InstallingAsyncTask extends AsyncTask<Void, Void,
            PackageInstaller.Session> {
        volatile boolean isDone;

        @Override
        protected PackageInstaller.Session doInBackground(Void... params) {
       		...
        }

        @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);
				//注释0210 将PendingIntent的IntentSender通过PackageInstaller.Session的commit方法发送出去
                session.commit(pendingIntent.getIntentSender());
                mCancelButton.setEnabled(false);
                setFinishOnTouchOutside(false);
            } else {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);

                if (!isCancelled()) {
                    launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null);
                }
            }
        }
    }
}
  • 在onCreate方法中会分别对package和content协议的Uri进行处理,我们来看content协议的Uri处理部分。注释1处如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId,其中mSessionId是安装包的会话id,mInstallId是等待的安装事件id。注释2处根据mInstallId向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调,无论安装成功或者失败都会关闭当前的Activity(InstallInstalling)。如果savedInstanceState为null,代码的逻辑也是类似的,注释3处创建SessionParams,它用来代表安装会话的参数,注释4、5处根据mPackageUri对包(APK)进行轻量级的解析,并将解析的参数赋值给SessionParams。注释6处和注释2处类似向InstallEventReceiver注册一个观察者返回一个新的mInstallId,其中InstallEventReceiver继承自BroadcastReceiver,用于接收安装事件并回调给EventResultPersister。 注释7处PackageInstaller的createSession方法内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId。
  • 继续查看InstallInstalling的onResume方法,在【注释0208】处根据mSessionId得到SessionInfo,SessionInfo代表安装会话的详细信息。【注释0209】处如果sessionInfo不为Null并且不是活动的,就创建并执行InstallingAsyncTask。InstallingAsyncTask的doInBackground方法中会根据包(APK)的Uri,将APK的信息通过IO流的形式写入到PackageInstaller.Session中。
  • 继续看InstallInstalling的内部类InstallingAsyncTask的onPostExecute方法,该方法内部创建了一个PendingIntent,并将该PendingIntent的IntentSender通过【注释0210】处的PackageInstaller.Session的commit方法发送出去。
  • 继续查看PackageInstaller.Session的commit方法:

frameworks/base/core/java/android/content/pm/PackageInstaller.java

public class PackageInstaller {
    ...
   public static class Session implements Closeable {
        private IPackageInstallerSession mSession;
        /** {@hide} */
        public Session(IPackageInstallerSession session) {
            mSession = session;
        }
		...
        public void commit(@NonNull IntentSender statusReceiver) {
            try {
                mSession.commit(statusReceiver, false);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        ...
    }
    ...
}

mSession的类型为IPackageInstallerSession,这说明要通过IPackageInstallerSession来进行进程间的通信,最终会调用PackageInstallerSession的commit方法,这样代码逻辑就到了Java框架层的。

3.Java框架层的处理

frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java

public class PackageInstallerSession extends IPackageInstallerSession.Stub {
	  ...
	 private final Handler.Callback mHandlerCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
              	...
                case MSG_COMMIT:
                    synchronized (mLock) {
                        try {
                        	//注释0304 
                            commitLocked();
                        } catch (PackageManagerException e) {
                            final String completeMsg = ExceptionUtils.getCompleteMessage(e);
                            Slog.e(TAG,
                                    "Commit of session " + sessionId + " failed: " + completeMsg);
                            destroyInternal();
                            //注释0306 调用分发会话结束消息的方法
                            dispatchSessionFinished(e.error, completeMsg, null);
                        }
                    }
                    break;
                case MSG_ON_PACKAGE_INSTALLED:
                    final SomeArgs args = (SomeArgs) msg.obj;
                    final String packageName = (String) args.arg1;
                    final String message = (String) args.arg2;
                    final Bundle extras = (Bundle) args.arg3;
                    final IPackageInstallObserver2 observer = (IPackageInstallObserver2) args.arg4;
                    final int returnCode = args.argi1;
                    args.recycle();

                    try {
                    	//注释0308 调用观察者的方法 
                        observer.onPackageInstalled(packageName, returnCode, message, extras);
                    } catch (RemoteException ignored) {
                    }

                    break;
               	...
            }
            return true;
        }
    };
	...
	  public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
            Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
            String installerPackageName, int installerUid, SessionParams params, long createdMillis,
            File stageDir, String stageCid, boolean prepared, boolean sealed) {
			...
			mPm = pm;
			//注释0301 
        	mHandler = new Handler(looper, mHandlerCallback);
        	...
        }
	...
	@Override
    public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
        Preconditions.checkNotNull(statusReceiver);
        final boolean wasSealed;
        synchronized (mLock) {
            assertCallerIsOwnerOrRootLocked();
            assertPreparedAndNotDestroyedLocked("commit");
			//将包的信息封装为PackageInstallObserverAdapter ,它在PMS中被定义
            final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
                    mContext, statusReceiver, sessionId,
                    isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
            //注释0302 其中adapter.getBinder()会得到IPackageInstallObserver2.Stub类型的观察者,从类型就知道这个观察者是可以跨进程进行回调的。        
            mRemoteObserver = adapter.getBinder();
			...
			//注释0303 向Handler发送一个类型为MSG_COMMIT的消息,其中adapter.getBinder()会得到IPackageInstallObserver2.Stub类型的观察者
            mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
        }
		...
    }
	...
	 @GuardedBy("mLock")
    private void commitLocked() throws PackageManagerException {
    	...
    	//注释0305 
        mPm.installStage(mPackageName, stageDir, localObserver, params,
                mInstallerPackageName, mInstallerUid, user, mSigningDetails);
    }
	...
	 private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
        final IPackageInstallObserver2 observer;
        final String packageName;
        synchronized (mLock) {
            mFinalStatus = returnCode;
            mFinalMessage = msg;

            observer = mRemoteObserver;
            packageName = mPackageName;
        }

        if (observer != null) {
            // Execute observer.onPackageInstalled on different tread as we don't want callers
            // inside the system server have to worry about catching the callbacks while they are
            // calling into the session
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = packageName;
            args.arg2 = msg;
            args.arg3 = extras;
            args.arg4 = observer;
            args.argi1 = returnCode;
			//注释0307 
            mHandler.obtainMessage(MSG_ON_PACKAGE_INSTALLED, args).sendToTarget();
        }

        final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED);

        // Send broadcast to default launcher only if it's a new install
        final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
        if (success && isNewInstall) {
            mPm.sendSessionCommitBroadcast(generateInfo(), userId);
        }

        mCallback.onSessionFinished(this, success);
    }
    ...

}
  • 在PackageInstallerSession的commit方法中,首先会将包信息封装为PackageInstallObserverAdapter ,它是在PMS中定义的,在【注释0302】处通过adapter.getBinder获得跨进程通信的观察者,并使用mHandler发送消息MSG_COMMIT,触发mHandlerCallback的handleMessage方法,mHandler对象是在【注释0306】处初始化的。
  • 继续查看mHandlerCallback类的handleMessage方法,在【注释0304】处调用PackageInstallerSession对象的commitLocked方法,而在commitLocked方法的最后,调用PackageManagerService的installStage方法,这样代码逻辑就进入到了PMS中。

4、重新回到mHandlerCallback的handleMessage方法中,如果commitLocked方法出现PackageManagerException异常,就会调用【注释0306】处的dispatchSessionFinished方法,在该方法中又会在【**注释0307 **】处发送消息MSG_ON_PACKAGE_INSTALLED,最终
mHandlerCallback对象会在【**注释0307 **】处调用IPackageInstallObserver2 的onPackageInstalled,该类的具体是实现在PackageInstallObserver类中,

/frameworks/base/core/java/android/app/PackageInstallObserver.java

public class PackageInstallObserver {
    private final IPackageInstallObserver2.Stub mBinder = new IPackageInstallObserver2.Stub() {
        @Override
        public void onUserActionRequired(Intent intent) {
            PackageInstallObserver.this.onUserActionRequired(intent);
        }

        @Override
        public void onPackageInstalled(String basePackageName, int returnCode,
                String msg, Bundle extras) {
            //注释0401 调用PackageInstallObserver的方法,PackageInstallObserver的具体实现子类为PackageInstallObserverAdapter
            PackageInstallObserver.this.onPackageInstalled(basePackageName, returnCode, msg, extras);
        }
    };

    /** {@hide} */
    public IPackageInstallObserver2 getBinder() {
        return mBinder;
    }

    public void onUserActionRequired(Intent intent) {
    }

    public void onPackageInstalled(String basePackageName, int returnCode, String msg,
            Bundle extras) {
    }
}

在【注释0401】处调用了PackageInstallObserver的onPackageInstalled方法,实现这个方法的类为PackageInstallObserver的子类、前面提到的PackageInstallObserverAdapter。总结一下就是dispatchSessionFinished方法会通过mRemoteObserver的onPackageInstalled方法,将Complete方法出现的PackageManagerException的异常信息回调给PackageInstallObserverAdapter。

5、总结
本篇文章主要讲解了PackageInstaller安装APK的过程,简单来说就两步:

  • 将APK的信息通过IO流的形式写入到PackageInstaller.Session中。
  • 调用PackageInstaller.Session的commit方法,将APK的信息交由PMS处理。

由于PMS中对APK安装的处理比较复杂,因此关于PMS的处理部分会在本系列的下一篇文章进行讲解。