Preface

In the last article in this series Android Package management mechanism ( One )PackageInstaller We learned from the initialization of PackageInstaller How to initialize , We'll continue to learn about this article PackageInstaller How to install APK Of . The source code of this series of articles is based on Android8.0.

1.PackageInstaller Processing in

This is followed by the previous article , stay PackageInstallerActivity call startInstallConfirm Method to initialize the installation confirmation interface , The installation confirmation interface will be presented to the user , If the user wants to install the application, he will click the OK button , Will call PackageInstallerActivity Of onClick Method , As shown below .
packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java

public void onClick(View v) {
if (v == mOk) {
if (mOk.isEnabled()) {
if (mOkCanInstall || mScrollView == null) {
if (mSessionId != -) {
mInstaller.setPermissionsResult(mSessionId, true);
finish();
} else {
startInstall();//
}
} else {
mScrollView.pageScroll(View.FOCUS_DOWN);
}
}
} else if (v == mCancel) {
...
finish();
}
}

onClick Method to process the OK and Cancel buttons respectively , Mainly view the processing of OK button , notes 1 Called startInstall Method :
packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java

private void startInstall() {
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(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
startActivity(newIntent);
finish();
}

startInstall Method is used to jump to InstallInstalling This Activity, And shut down the current PackageInstallerActivity.InstallInstalling It is mainly used to send packet information to packet manager and handle callback of packet management . InstallInstalling Of onCreate The method is as follows .
packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

@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 {
// according to mPackageURI Create a corresponding File
final File sourceFile = new File(mPackageURI.getPath());
PackageUtil.initSnippetForNewApp(this, PackageUtil.getAppSnippet(this, appInfo,
sourceFile), R.id.app_snippet);
// If savedInstanceState Not for null, Get previously saved mSessionId and mInstallId
if (savedInstanceState != null) {//
mSessionId = savedInstanceState.getInt(SESSION_ID);
mInstallId = savedInstanceState.getInt(INSTALL_ID);
// towards InstallEventReceiver Register an observer
try {
InstallEventReceiver.addObserver(this, mInstallId,
this::launchFinishBasedOnResult);//
} catch (EventResultPersister.OutOfIdsException e) { }
} else {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);//
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);
File file = new File(mPackageURI.getPath());//
try {
PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, );//
params.setAppPackageName(pkg.packageName);
params.setInstallLocation(pkg.installLocation);
params.setSize(
PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
} catch (PackageParser.PackageParserException e) {
...
}
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);
}
}
...
mSessionCallback = new InstallSessionCallback();
}
}

onCreate In the method, we will separate package and content Agreed Uri To deal with , Let's see content Agreed Uri processing section . notes 1 If you are savedInstanceState Not for null, Get previously saved mSessionId and mInstallId, among mSessionId Is the session to install the package id,mInstallId Is a waiting installation event id. notes 2 According to mInstallId towards InstallEventReceiver Register an observer ,launchFinishBasedOnResult Will receive a callback for the installation event , Whether the installation succeeds or fails, the current Activity(InstallInstalling). If savedInstanceState by null, The logic of the code is similar , notes 3 Created at SessionParams, It is used to represent the parameters of the installation session , notes 4、5 According to mPackageUri To pack (APK) For lightweight parsing , And assign the parsed parameters to SessionParams. notes 6 And notes 2 It's similar to InstallEventReceiver Register an observer and return a new mInstallId, among InstallEventReceiver Inherited from BroadcastReceiver, Used to receive installation events and call back to EventResultPersister. notes 7 It's about PackageInstaller Of createSession The method will pass through IPackageInstaller And PackageInstallerService Communication between processes , The final call is PackageInstallerService Of createSession Method to create and return mSessionId.
InstallInstalling Of onCreate This is the analysis of the method , Then check InstallInstalling Of onResume Method :
packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

@Override
protected void onResume() {
super.onResume();
if (mInstallingTask == null) {
PackageInstaller installer = getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);//
if (sessionInfo != null && !sessionInfo.isActive()) {//
mInstallingTask = new InstallingAsyncTask();
mInstallingTask.execute();
} else {
mCancelButton.setEnabled(false);
setFinishOnTouchOutside(false);
}
}
}

notes 1 According to mSessionId obtain SessionInfo,SessionInfo Represents the details of the installation session . notes 2 If you are sessionInfo Not for Null And not active , Just create and execute InstallingAsyncTask.InstallingAsyncTask Of doInBackground Method will be based on the package (APK) Of Uri, take APK Information through IO Write to as a stream PackageInstaller.Session in .InstallingAsyncTask Of onPostExecute The method is as follows .
packages/apps/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java

@Override
protected void onPostExecute(PackageInstaller.Session session) {
if (session != null) {
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
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);
}
}
}

Created a PendingIntent, And put the PendingIntent Of IntentSender By annotating 1 Situated PackageInstaller.Session Of commit Method send out , Where did it go ? Then check PackageInstaller.Session Of commit Method .
frameworks/base/core/java/android/content/pm/PackageInstaller.java

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

mSession The type of IPackageInstallerSession, It means to pass IPackageInstallerSession To communicate between processes , Will eventually call PackageInstallerSession Of commit Method , So that's the logic of the code Java Frame layer .

2.Java The processing of frame layer

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

@Override
public void commit(IntentSender statusReceiver) {
Preconditions.checkNotNull(statusReceiver);
...
mActiveCount.incrementAndGet();
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);
mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();//
}

commit Method encapsulates the package information as PackageInstallObserverAdapter , It's in PMS Is defined in . In the comments 1 The Department will report to you Handler Send a type of MSG_COMMIT The news of , among adapter.getBinder() You'll get IPackageInstallObserver2.Stub The type of observer , We know from the type that this observer can callback across processes . The code to process the message is as follows .
frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java

private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
final PackageInfo pkgInfo = mPm.getPackageInfo(
params.appPackageName, PackageManager.GET_SIGNATURES
| PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
final ApplicationInfo appInfo = mPm.getApplicationInfo(
params.appPackageName, , userId);
synchronized (mLock) {
if (msg.obj != null) {
mRemoteObserver = (IPackageInstallObserver2) msg.obj;//
}
try {
commitLocked(pkgInfo, appInfo);//
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
destroyInternal();
dispatchSessionFinished(e.error, completeMsg, null);//
}
return true;
}
}
};

notes 1 Get IPackageInstallObserver2 The type of observer mRemoteObserver, notes 2 Situated commitLocked The method is as follows .
frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java

private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
throws PackageManagerException {
...
mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
installerPackageName, installerUid, user, mCertificates);
}

commitLocked The method is longer , The most important information is intercepted here , Would call PMS Of installStage Method , So the code logic goes into PMS in .
go back to mHandlerCallback Of handleMessage Method , If commitLocked Methods appear PackageManagerException abnormal , The comment is called 3 Situated dispatchSessionFinished Method , Its implementation is as follows :
frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java

private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
mFinalStatus = returnCode;
mFinalMessage = msg;
if (mRemoteObserver != null) {
try {
mRemoteObserver.onPackageInstalled(mPackageName, returnCode, msg, extras);//
} catch (RemoteException ignored) {
}
}
...
}

notes 1 Will call IPackageInstallObserver2 Of onPackageInstalled Method , Specifically, it is realized in PackageInstallObserver Class :
frameworks/base/core/java/android/app/PackageInstallObserver.java

public class PackageInstallObserver {
private final IPackageInstallObserver2.Stub mBinder = new IPackageInstallObserver2.Stub() {
...
@Override
public void onPackageInstalled(String basePackageName, int returnCode,
String msg, Bundle extras) {
PackageInstallObserver.this.onPackageInstalled(basePackageName, returnCode, msg,
extras);//
}
};

notes 1 Called PackageInstallObserver Of onPackageInstalled Method , The class that implements this method is PackageInstallObserver Subclasses of 、 aforementioned PackageInstallObserverAdapter. So in summary dispatchSessionFinished The method will pass mRemoteObserver Of onPackageInstalled Method , take Complete Methods appear PackageManagerException Call back to PackageInstallObserverAdapter.

3. summary

This article explains PackageInstaller install APK The process of , In short, it's just two steps :

  1. take APK Information through IO Write to as a stream PackageInstaller.Session in .
  2. call PackageInstaller.Session Of commit Method , take APK I'll leave it to you PMS Handle .

because PMS Chinese vs APK The process of installation is complicated , So about PMS The processing section of will be explained in the next article in this series .

Android Package management mechanism ( Two )PackageInstaller install APK More articles about

  1. Android Package management mechanism ( One ) PackageInstaller The initialization

    Preface The package management mechanism is Android An important mechanism in , It is one of the knowledge points that application development and system development need to master . What does Bao mean Apk.jar and so Documents, etc. , They are loaded into Android In the memory , From a package to executable code , It takes a long time ...

  2. Android Thread management ( Two )——ActivityThread

    Thread communication .ActivityThread And Thread Class is understanding Android The key to thread management . Threads , As CPU The basic unit of scheduling resources , stay Android And other operating systems for embedded devices , It plays a very important and fundamental role . ...

  3. Front-end engineering - analyse npm Package management mechanism of

    from https://juejin.im/post/5df789066fb9a0161f30580c Today, , The students of front-end development are inseparable from npm This package management tool , Its excellent package version management mechanism carries the entire prosperity of ...

  4. Using copy mode (adb push) Bypass Android Systems and adb install Direct installation APK

    In some cases, customized Android In order to limit users to install applications , Like a TV box , Vehicle central control, etc , By modifying the code, the normal installation of the application is masked This paper discusses how to use adb shell With reading and writing data Under the permission of partition Directory , adopt a ...

  5. 【 Morning flowers and evening flowers 】Android Performance ( 6、 ... and )Android Process management mechanism

    Preface        Android The system is very different from other operating systems , That is, other operating systems remove inactive processes as much as possible , So as to ensure as much memory space as possible , and Android The system is the opposite , Keep the process as much as possible .An ...

  6. ubuntu Package management mechanism

    1 ubuntu Package management mechanism Share with you ubuntu The software management mechanism of . If you've ever had : apt-get install perhaps apt-get update The experience of failure . In many apt Lost in command . doubt ...

  7. iOS Package management tools Cocoapods Installation and use of

    from :http://www.sxt.cn/u/10014/blog/6448 When we develop mobile applications , Third party tools are usually used , Because of the variety of third-party class libraries , We are also relatively troublesome in project management , So at this time ...

  8. Android Research on process management mechanism

    One .Linux Process management in Linux in , A process is an instance of execution on a processor , Any resource can be used to accomplish its task , Specific process management , It's through “ Process descriptors ” To complete , Corresponding Linux Kernel task_struct data ...

  9. Node: Package management mechanism

    Node.js The module mechanism of can solve the problem of business code confusion very well , But for third-party module packages , I just can't do it , Because the third-party module packages are scattered around , No centralized management . This requires a package management mechanism , stay Node.js in ,Isa ...

Random recommendation

  1. ionic cordova Some problems of hot update

    Because the project needs to update this piece , So I checked cordova Hot update of , Then I met Some of the problems , Take notes . The project uses ionic download cordova Just skip the content of . First, download cordova The insertion of ...

  2. different windows phone (52) - 8.1 New control : AutoSuggestBox, ListView, GridView, SemanticZoom

    [ Source download ] different windows phone (52) - 8.1 New control : AutoSuggestBox, ListView, GridView, SemanticZoom author :webab ...

  3. Incisive jQuery The first 2 Edition learning notes 1~3 Chapter

    The first 1 Chapter , know jQuery Be careful : The use of jQuery Version is 1.7.1 current JavaScript library Prototype(http://www.prototypejs.org), It's early , Object-oriented thinking ...

  4. Simple python2.7.3 install setuptools modular

    download setuptools https://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg install .6c11- ...

  5. To configure Log4J( Reprint )

    Log4J Configuration file for (Configuration File) It's used to set the level of the recorder . Storage and layout of , It can connect key=value Format setting or xml Format setting information . By configuring , You can create Log4J Operating environment ...

  6. I want you to understand Java in volatile Keyword implementation principle

    Original address http://www.cnblogs.com/xrq730/p/7048693.html, Reprint please indicate the source , thank you Preface We know volatile Keyword is used to ensure the visibility of variables among multiple threads , It is j ...

  7. Scrapy Examples of reptiles —— School flower net

    I've been learning reptiles for a while , Use today Scrapy The frame crawls the pictures of xuehua.com to the local .Scrapy Crawler framework is relative to using requests Library for web crawling , With higher performance . Scrapy The official definition of :Scrapy It's for grabbing nets ...

  8. SmartSql Cache label

    Demo <Cache Id="T_Test.LruCache" Type="Lru"> <Parameter Key="Cache ...

  9. ubuntu16.04 anaconda Install and uninstall

    First installation : 1. Download it directly from the official website anaconda Installation package , then bash ...sh install . 2. In the process, you need to choose the installation path , In order to put all the installed software together , I have a new one install_software In system ...

  10. Operating Systems (COMP2006)

    Operating Systems (COMP2006) 1st Semester 2019Page 1, CRICOS Number: 00301JOperating Systems (COMP20 ...