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的处理部分会在本系列的下一篇文章进行讲解。