700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android 9.0系统源码_包管理机制(二)PackageInstaller安装APK

Android 9.0系统源码_包管理机制(二)PackageInstaller安装APK

时间:2020-03-17 13:57:02

相关推荐

Android 9.0系统源码_包管理机制(二)PackageInstaller安装APK

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 finishsetResult(RESULT_CANCELED);if (mSessionId != -1) {mInstaller.setPermissionsResult(mSessionId, false);}finish();}}//startInstall方法用于跳转到InstallInstalling这个Activity,并关闭掉当前的PackageInstallerActivityprivate void startInstall() {// Start subactivity to actually install the applicationIntent 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 {...@Overrideprotected 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会接收到安装事件的回调,无论安装成功或者失败都会关闭当前ActivityInstallEventReceiver.addObserver(this, mInstallId,this::launchFinishBasedOnResult);} catch (EventResultPersister.OutOfIdsException e) {// Does not happen}} else {//注释0203PackageInstaller.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);//注释0204File file = new File(mPackageURI.getPath());try {//注释0205PackageParser.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 {//注释0206mInstallId = InstallEventReceiver.addObserver(this, EventResultPersister.GENERATE_NEW_ID,this::launchFinishBasedOnResult);} catch (EventResultPersister.OutOfIdsException e) {launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);}try {//注释0207mSessionId = getPackageManager().getPackageInstaller().createSession(params);} catch (IOException e) {launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);}}...mSessionCallback = new InstallSessionCallback();}}...@Overrideprotected void onResume() {super.onResume();// This is the first onResume in a single life of the activityif (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 finishedmCancelButton.setEnabled(false);setFinishOnTouchOutside(false);}}}...//内部类private final class InstallingAsyncTask extends AsyncTask<Void, Void,PackageInstaller.Session> {volatile boolean isDone;@Overrideprotected PackageInstaller.Session doInBackground(Void... params) {...}@Overrideprotected 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方法发送出去mit(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 {mit(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() {@Overridepublic 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);...}...@Overridepublic 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 sessionfinal 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 installfinal 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() {@Overridepublic void onUserActionRequired(Intent intent) {PackageInstallObserver.this.onUserActionRequired(intent);}@Overridepublic void onPackageInstalled(String basePackageName, int returnCode,String msg, Bundle extras) {//注释0401 调用PackageInstallObserver的方法,PackageInstallObserver的具体实现子类为PackageInstallObserverAdapterPackageInstallObserver.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的处理部分会在本系列的下一篇文章进行讲解。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。