Android 10.0 PackageManagerService(四)APK安装流程-[Android取经之路]

[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析

[Android取经之路] 系列文章:

《系统启动篇》

Android系统架构
Android是怎么启动的
Android 10.0系统启动之init进程
Android10.0系统启动之Zygote进程
Android 10.0 系统启动之SystemServer进程
Android 10.0 系统服务之ActivityMnagerService
Android10.0系统启动之Launcher(桌面)启动流程
Android10.0应用进程创建过程以及Zygote的fork流程
Android 10.0 PackageManagerService(一)工作原理及启动流程
Android 10.0 PackageManagerService(二)权限扫描
Android 10.0 PackageManagerService(三)APK扫描
Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》

Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​
《Binder通信原理》:

Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
Android10.0 Binder通信原理(二)-Binder入门篇
Android10.0 Binder通信原理(三)-ServiceManager篇
Android10.0 Binder通信原理(四)-Native-C\C++实例分析
Android10.0 Binder通信原理(五)-Binder驱动分析
Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
Android10.0 Binder通信原理(七)-Framework binder示例
Android10.0 Binder通信原理(八)-Framework层分析
Android10.0 Binder通信原理(九)-AIDL Binder示例
Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
Android10.0 Binder通信原理(十一)-Binder总结

《HwBinder通信原理》

HwBinder入门篇-Android10.0 HwBinder通信原理(一)
 HIDL详解-Android10.0 HwBinder通信原理(二)
HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
HwServiceManager篇-Android10.0 HwBinder通信原理(五)
Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》

编译系统入门篇-Android10.0编译系统(一)
编译环境初始化-Android10.0编译系统(二)
make编译过程-Android10.0编译系统(三)
Image打包流程-Android10.0编译系统(四
Kati详解-Android10.0编译系统(五)
Blueprint简介-Android10.0编译系统(六)
Blueprint代码详细分析-Android10.0编译系统(七)
Android.bp 语法浅析-Android10.0编译系统(八)
Ninja简介-Android10.0编译系统(九)
Ninja提升编译速度的方法-Android10.0编译系统(十)
Android10.0编译系统(十一)

1.概述
Android应用安装有如下四种方式:

1)系统应用和预制应用安装――开机时完成,没有安装界面,在PKMS的构造函数中完成安装

2)网络下载应用安装――通过应用商店应用完成,调用PackageManager.installPackages(),有安装界面。

3)ADB工具安装――没有安装界面,它通过启动pm脚本的形式,然后调用com.android.commands.pm.Pm类,之后调用到PMS.installStage()完成安装。

4)第三方应用安装――通过SD卡里的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面。

上述几种方式均通过PackageInstallObserver来监听安装是否成功。

 

2.代码路径
 

/frameworks/base/packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
/frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
/frameworks/base/core/java/android/content/pm/IPackageInstallerSession.aidl 
/frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java 
/frameworks/base/services/core/java/com/android/server/pm/Installer.java
/system/core/adb/client/commandline.cpp
/system/core/adb/client/adb_install.cpp
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java

3.APK的包组成

    生成的APK文件本质还是一个zip文件,只不过被Google强行修改了一下后缀名称而已。所以我们将APK的后缀修改成.zip就可以查看其包含的内容了。

如下图所示:

 

META-INF:关于签名的信息存放,应用安装验证签名的时候会验证该文件里面的信息 -res:资源文件,是被编译过的。raw和图片是保持原样的,但是其他的文件会被编译成二进制文件。

res:这里面的资源是不经过编译原样打包进来的

AndroidManifest.xml:程序全局配置文件。该文件是每个应用程序都必须定义和包含的文件,它描述了应用程序的名字、版本、权限、引用的库文件等等信息。

classes.dex:Dalvik字节码文件,Android会将所有的class文件全部放到这一个文件里。

resources.arsc:编译后的二进制资源文件,保存资源文件的索引,由aapt生成

lib: 如果存在的话,存放的是ndk编出来的so库

4.APK的打包过程
打包具体步骤如下图所示:

编译器将源代码转换成DEX(Dalvik Executable) 文件,将资源文件转换成已编译资源。

    APK打包器将DEX文件和已编译资源合并成单个APK。不过,必须先将APK签名,才能将应用安装并部署到Android设备上。

    APK打包器使用密钥签署APK:a. 如果构建的APK是debug版本,那么将使用调试密钥签名,Android会默认提供一个debug的密钥。b. 如果构建的是release版本,会使用发布版本的密钥签名。

    在生成最终的APK文件之前还会使用zipalign工具来优化文件。

5.APK SignatureSchemev2
    使用V2的原因Android7.0(Nougat)引入一项新的应用签名方案APK SignatureSchemev2,它是一个对全文件进行签名的方案,能提供更快的应用安装时间、对未授权APK文件的更改提供更多保护.v2signature官方解释同时V2方案对V1方案做了+很好的兼容处理(Apk中同时存在v1,v2签名)。

    V1签名apk-signature-v1-location.png只是校验了apk资源,并没有约束zip,签名信息存储在zip/META-INF中。

    APK Signature Scheme v2,它是一个对全文件进行签名的方案,能提供更快的应用安装时间、对未授权APK文件的更改提供更多保护.

如下图所示:

新的签名方案会在ZIP文件格式的 Central Directory 区块所在文件位置的前面添加一个APK Signing Block区块,下面按照ZIP文件的格式来分析新应用签名方案签名后的APK包。整个APK(ZIP文件格式)会被分为以下四个区块:

Contents of ZIP entries(from offset 0 until the start of APK Signing Block)

APK Signing Block

ZIP Central Directory

ZIP End of Central Directory

    新应用签名方案的签名信息会被保存在区块2(APK Signing Block)中, 而区块1(Contents of ZIP entries)、区块3(ZIP Central Directory)、区块4(ZIP End of Central Directory)是受保护的,在签名后任何对区块1、3、4的修改都逃不过新的应用签名方案的检查。

 

6.APK的安装过程
    这里我们主要来讲解下载APK后,点击进行安装的过程。

    简单来说分为四步:

1)将APK的信息通过IO流的形式写入到PackageInstaller.Session中。

2)调用PackageInstaller.Session的commit方法,将APK的信息交由PKMS处理。

3)拷贝APK

4)最后进行安装

 

涉及的Binder服务:

1)PackageManager(抽象类)----IPackageManager------ PKMS

(实现类:ApplicationPackageManager )

2)PackageInstaller-----IPackageInstaller------PackageInstallerService

(其中会调用IPackageInstaller对象调用PackageInstallerService中的接口)

3)PackageInstaller.Session-----IPackageInstallerSession------ PackageInstallerSession

    (PackageInstaller.Session中有IPackageInstallerSession类型的成员变量,来调用 PackageInstallerSession的接口)

点击安装后到完成APK 拷贝的流程如下:

 

点击一个未安装的apk后,会弹出安装界面,点击点击确定按钮后,会进入 PackageInstallerActivity.java的 bindUi()中的mAlert点击事件

点击apk后,弹出的安装界面底部显示的是一个diaglog,主要由bindUi构成,上面有”取消“和”安装“两个按钮,点击安装后 调用startInstall()进行安装

private void bindUi() {
    mAlert.setIcon(mAppSnippet.icon);
    mAlert.setTitle(mAppSnippet.label);
    mAlert.setView(R.layout.install_content_view);
    mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
            (ignored, ignored2) -> {
                if (mOk.isEnabled()) {
                    if (mSessionId != -1) {
                        mInstaller.setPermissionsResult(mSessionId, true);
                        finish();
                    } else {
                        startInstall();  //进行APK安装
                    }
                }
            }, null);
    mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
            (ignored, ignored2) -> {
                // Cancel and finish
                setResult(RESULT_CANCELED);
                if (mSessionId != -1) {
                    //如果mSessionId存在,执行setPermissionsResult()完成取消安装
                    mInstaller.setPermissionsResult(mSessionId, false);
                }
                finish();
            }, null);
    setupAlert();
 
    mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
    mOk.setEnabled(false);
}

startInstall方法组装了一个Intent,并跳转到 InstallInstalling 这个Activity,并关闭掉当前的PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调。

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);  //设置Intent中的class为 InstallInstalling,用来进行Activity跳转
    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();
}

InstallInstalling 的Activity启动后,进入onCreate

主要分为6步:

1.如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId,其中mSessionId是安装包的会话id,mInstallId是等待的安装事件id

2.根据mInstallId向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调,无论安装成功或者失败都会关闭当前的Activity(InstallInstalling)。如果savedInstanceState为null,代码的逻辑也是类似的

3.创建SessionParams,它用来代表安装会话的参数,组装params

4.根据mPackageUri对包(APK)进行轻量级的解析,并将解析的参数赋值给SessionParams

5.向InstallEventReceiver注册一个观察者返回一个新的mInstallId,其中InstallEventReceiver继承自BroadcastReceiver,用于接收安装事件并回调给EventResultPersister。

6.PackageInstaller的createSession方法内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId

protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
 
    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.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
 
        mAlert.setIcon(as.icon);
        mAlert.setTitle(as.label);
        mAlert.setView(R.layout.install_content_view);
        mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
                (ignored, ignored2) -> {
                    if (mInstallingTask != null) {
                        mInstallingTask.cancel(true);
                    }
 
                    if (mSessionId > 0) {
                        getPackageManager().getPackageInstaller().abandonSession(mSessionId);
                        mSessionId = 0;
                    }
 
                    setResult(RESULT_CANCELED);
                    finish();
                }, null);
        setupAlert();
        requireViewById(R.id.installing).setVisibility(View.VISIBLE);
 
        //1.如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId,其中mSessionId是安装包的会话id,mInstallId是等待的安装事件id
        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 {
                //2.根据mInstallId向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调,
                //无论安装成功或者失败都会关闭当前的Activity(InstallInstalling)。如果savedInstanceState为null,代码的逻辑也是类似的
                InstallEventReceiver.addObserver(this, mInstallId,
                        this::launchFinishBasedOnResult);
            } catch (EventResultPersister.OutOfIdsException e) {
                // Does not happen
            }
        } else {
            //3.创建SessionParams,它用来代表安装会话的参数,组装params
            PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            params.setInstallAsInstantApp(false);
            params.setReferrerUri(getIntent().getParcelableExtra(Intent.EXTRA_REFERRER));
            params.setOriginatingUri(getIntent()
                    .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI));
            params.setOriginatingUid(getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
                    UID_UNKNOWN));
            params.setInstallerPackageName(getIntent().getStringExtra(
                    Intent.EXTRA_INSTALLER_PACKAGE_NAME));
            params.setInstallReason(PackageManager.INSTALL_REASON_USER);
 
            //4.根据mPackageUri对包(APK)进行轻量级的解析,并将解析的参数赋值给SessionParams
            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 {
                //5.向InstallEventReceiver注册一个观察者返回一个新的mInstallId,
                //其中InstallEventReceiver继承自BroadcastReceiver,用于接收安装事件并回调给EventResultPersister。
                mInstallId = InstallEventReceiver
                        .addObserver(this, EventResultPersister.GENERATE_NEW_ID,
                                this::launchFinishBasedOnResult);
            } catch (EventResultPersister.OutOfIdsException e) {
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }
 
            try {
                //6.PackageInstaller的createSession方法内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,
                //最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId
                mSessionId = getPackageManager().getPackageInstaller().createSession(params);
            } catch (IOException e) {
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }
        }
 
        mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE);
 
        mSessionCallback = new InstallSessionCallback();
    }
}

这里 PackageInstaller 的 createSession()内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId。

    接着在InstallInstalling 的onResume方法中,调用onPostExecute()方法,将APK的信息通过IO流的形式写入到PackageInstaller.Session中
 

protected void onResume() {
    super.onResume();
    // This is the first onResume in a single life of the activity
    if (mInstallingTask == null) {
        PackageInstaller installer = getPackageManager().getPackageInstaller();
        //获取sessionInfo
        PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);
 
        if (sessionInfo != null && !sessionInfo.isActive()) {
            //创建内部类InstallingAsyncTask的对象,调用execute(),最终进入onPostExecute()
            mInstallingTask = new InstallingAsyncTask();
            mInstallingTask.execute();
        } else {
            // we will receive a broadcast when the install is finished
            mCancelButton.setEnabled(false);
            setFinishOnTouchOutside(false);
        }
    }
}

 InstallingAsyncTask 的doInBackground()会根据包(APK)的Uri,将APK的信息通过IO流的形式写入到PackageInstaller.Session中

最后在onPostExecute()中 调用PackageInstaller.Session的commit方法,进行安装
 

 
private final class InstallingAsyncTask extends AsyncTask<Void, Void,
        PackageInstaller.Session> {
    volatile boolean isDone;
 
    @Override
    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;
                        }
                        //将APK的信息通过IO流的形式写入到PackageInstaller.Session中
                        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(getPackageName());
            broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId);
 
            PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    InstallInstalling.this,
                    mInstallId,
                    broadcastIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
 
            调用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);
            }
        }
    }
}

接下来看一看PackageInstaller的commit()

[PackageInstaller.java] commit
public void commit(@NonNull IntentSender statusReceiver) {
    try {
        //调用PackageInstallerSession的commit方法,进入到java框架层
        mSession.commit(statusReceiver, false);
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

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

[PackageInstallerSession.java] commit()
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
    if (mIsPerfLockAcquired && mPerfBoostInstall != null) {
        mPerfBoostInstall.perfLockRelease();
        mIsPerfLockAcquired = false;
    }
    ...
    //调用markAsCommitted()
    if (!markAsCommitted(statusReceiver, forTransfer)) {
        return;
    }
    ...
    mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
}

markAsCommitted方法中会将包的信息封装为 PackageInstallObserverAdapter ,它在PKMS中被定义,然后返回到commit()中,向Handler发送一个类型为MSG_COMMIT的消息

public boolean markAsCommitted(
        @NonNull IntentSender statusReceiver, boolean forTransfer) {
    Preconditions.checkNotNull(statusReceiver);
 
    List<PackageInstallerSession> childSessions = getChildSessions();
 
    final boolean wasSealed;
    synchronized (mLock) {
        assertCallerIsOwnerOrRootLocked();
        assertPreparedAndNotDestroyedLocked("commit");
 
        final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
                mContext, statusReceiver, sessionId,
                isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
        mRemoteObserver = adapter.getBinder();
    ...
    return true;
}

MSG_COMMIT在handler中进行处理,进入handleCommit()

public boolean handleMessage(Message msg) {
    switch (msg.what) {
        case MSG_COMMIT:
            handleCommit();
            break;
    }
}
 
private void handleCommit() {
    ...
    List<PackageInstallerSession> childSessions = getChildSessions();
 
    try {
        synchronized (mLock) {
            //最终调用installStage(),进入PKMS
            commitNonStagedLocked(childSessions);
        }
    } catch (PackageManagerException e) {
        final String completeMsg = ExceptionUtils.getCompleteMessage(e);
        Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
        destroyInternal();
        dispatchSessionFinished(e.error, completeMsg, null);
    }
}

 commitNonStagedLocked()中首先 调用了PackageInstallObserver的 onPackageInstalled方法,将 Complete 方法出现的PackageManagerException的异常信息回调给

PackageInstallObserverAdapter。

最终调用installStage(),进入PKMS
 

private void commitNonStagedLocked(List<PackageInstallerSession> childSessions)
        throws PackageManagerException {
    if (isMultiPackage()) {
        ...
        if (!success) {
            try {
                mRemoteObserver.onPackageInstalled(
                        null, failure.error, failure.getLocalizedMessage(), null);
            } catch (RemoteException ignored) {
            }
            return;
        }
        mPm.installStage(activeChildSessions);
    } else {
        mPm.installStage(committingSession);
    }
}

进入PKMS的installStage()

 
void installStage(ActiveInstallSession activeInstallSession) {
    if (DEBUG_INSTANT) {
        if ((activeInstallSession.getSessionParams().installFlags
                & PackageManager.INSTALL_INSTANT_APP) != 0) {
            Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
        }
    }
    //1.创建了类型为INIT_COPY的消息
    final Message msg = mHandler.obtainMessage(INIT_COPY);
 
    //2.创建InstallParams,它对应于包的安装数据
    final InstallParams params = new InstallParams(activeInstallSession);
    params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
    msg.obj = params;
 
    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage",
            System.identityHashCode(msg.obj));
    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
            System.identityHashCode(msg.obj));
 
    //3.将InstallParams通过消息发送出去。
    mHandler.sendMessage(msg);
}
 
对INIT_COPY的消息的处理
[PackageManagerService.java]
void doHandleMessage(Message msg) {
    switch (msg.what) {
        case INIT_COPY: {
            HandlerParams params = (HandlerParams) msg.obj;
            if (params != null) {
                if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params);
                Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
                        System.identityHashCode(params));
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy");
                //执行APK拷贝动作
                params.startCopy();
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
            break;
        }
    }
}

handleStartCopy()需要执行下面几步:

1.首先检查文件和cid是否已生成,如生成则设置installFlags。

2.检查空间大小,如果空间不够则释放无用空间。

3.覆盖原有安装位置的文件,并根据返回结果来确定函数的返回值,并设置installFlags

4.确定是否有任何已安装的包验证器,如有,则延迟检测。主要分三步:首先新建一个验证Intent,然后设置相关的信息,之后获取验证器列表,最后向每个验证器发送验证Intent。
 

 
[PackageManagerService.java]
public void handleStartCopy() {
    //1.首先检查文件和cid是否已生成,如生成则设置installFlags。
    if (origin.staged) {
        if (origin.file != null) {
            installFlags |= PackageManager.INSTALL_INTERNAL;
        } else {
            throw new IllegalStateException("Invalid stage location");
        }
    }
    ...
    //2.检查空间大小,如果空间不够则释放无用空间。
    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 = PackageManagerServiceUtils.calculateInstalledSize(
                origin.resolvedPath, packageAbiOverride);
        if (sizeBytes >= 0) {
            try {
                mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
                pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
                        origin.resolvedPath, installFlags, packageAbiOverride);
            } catch (InstallerException e) {
                Slog.w(TAG, "Failed to free cache", e);
            }
        }
        if (pkgLite.recommendedInstallLocation
                == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
            pkgLite.recommendedInstallLocation
                    = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
        }
    }
 
    ...
    //3.覆盖原有安装位置的文件,并根据返回结果来确定函数的返回值,并设置installFlags。
    {
        // Override with defaults if needed.
        loc = installLocationPolicy(pkgLite);
        if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) {
            ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
        } else if (loc == PackageHelper.RECOMMEND_FAILED_WRONG_INSTALLED_VERSION) {
            ret = PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION;
        } else if (!onInt) {
            // Override install location with flags
            if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
                // Set the flag to install on external media.
                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_INTERNAL;
            } else {
                // Make sure the flag for installing on external
                // media is unset
                installFlags |= PackageManager.INSTALL_INTERNAL;
            }
        }
    }
    ...
    //4.确定是否有任何已安装的包验证器,如有,则延迟检测。主要分三步:首先新建一个验证Intent,然后设置相关的信息,之后获取验证器列表,最后向每个验证器发送验证Intent。
    //4.1构造验证Intent
    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);
 
    final PackageVerificationState verificationState = new PackageVerificationState(
            requiredUid, this);
 
    mPendingVerification.append(verificationId, verificationState);
     //4.2获取验证器列表
    final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
            receivers, verificationState);
 
    DeviceIdleController.LocalService idleController = getDeviceIdleController();
    final long idleDuration = getVerificationTimeout();
 
    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");
                //4.3向每个验证器发送验证Intent
                final Intent sufficientIntent = new Intent(verification);
                sufficientIntent.setComponent(verifierComponent);
                mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
            }
        }
    }
    ...
}

向验证器客户端发送intent,只有当验证成功之后才会开启copy工作。如果没有任何验证器则直接拷贝。

在handleReturnCode()中调用 copyApk()进行APK的拷贝动作

void handleReturnCode() {
    if (mVerificationCompleted && mEnableRollbackCompleted) {
        if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
            String packageName = "";
            try {
                PackageLite packageInfo =
                        new PackageParser().parsePackageLite(origin.file, 0);
                packageName = packageInfo.packageName;
            } catch (PackageParserException e) {
                Slog.e(TAG, "Can't parse package at " + origin.file.getAbsolutePath(), e);
            }
            try {
                observer.onPackageInstalled(packageName, mRet, "Dry run", new Bundle());
            } catch (RemoteException e) {
                Slog.i(TAG, "Observer no longer exists.");
            }
            return;
        }
        if (mRet == PackageManager.INSTALL_SUCCEEDED) {
            mRet = mArgs.copyApk();
        }
        processPendingInstall(mArgs, mRet);
    }
}

APK 拷贝调用栈如下:

 

通过文件流的操作,把APK拷贝到/data/app等目录

private static void copyFile(String sourcePath, File targetDir, String targetName)
        throws ErrnoException, IOException {
    if (!FileUtils.isValidExtFilename(targetName)) {
        throw new IllegalArgumentException("Invalid filename: " + targetName);
    }
    Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
 
    final File targetFile = new File(targetDir, targetName);
    final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
            O_RDWR | O_CREAT, 0644);
    Os.chmod(targetFile.getAbsolutePath(), 0644);
    FileInputStream source = null;
    try {
        source = new FileInputStream(sourcePath);
        FileUtils.copy(source.getFD(), targetFd);
    } finally {
        IoUtils.closeQuietly(source);
    }
}

APK拷贝完成后,进入真正的安装,流程如下:

 

 

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
    if (args.mMultiPackageInstallParams != null) {
        args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
    } else {
        //1.设置安装参数
        PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
        //2.创建一个新线程,处理安装参数,进行安装
        processInstallRequestsAsync(
                res.returnCode == PackageManager.INSTALL_SUCCEEDED,
                Collections.singletonList(new InstallRequest(args, res)));
    }
}
 
private void processInstallRequestsAsync(boolean success,
        List<InstallRequest> installRequests) {
    mHandler.post(() -> {
        if (success) {
            for (InstallRequest request : installRequests) {
                //1.如果之前安装失败,清除无用信息
                request.args.doPreInstall(request.installResult.returnCode);
            }
            synchronized (mInstallLock) {
                //2. installPackagesTracedLI 是安装过程的核心方法,然后调用 installPackagesLI 进行安装。
                installPackagesTracedLI(installRequests);
            }
            for (InstallRequest request : installRequests) {
                //3.如果之前安装失败,清除无用信息
                request.args.doPostInstall(
                        request.installResult.returnCode, request.installResult.uid);
            }
        }
        for (InstallRequest request : installRequests) {
            restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
                    new PostInstallData(request.args, request.installResult, null));
        }
    });
}

以原子方式安装一个或多个包。此操作分为五个阶段:

1)Prepare 准备:分析任何当前安装状态,分析包并对其进行初始验证。

2)Scan  扫描:考虑到prepare中收集的上下文,询问已分析的包。

3)Reconcile 调和:在彼此的上下文和当前系统状态中验证扫描的包,以确保安装成功。

4)Commit 提交:提交所有扫描的包并更新系统状态。这是安装流中唯一可以修改系统状态的地方,必须在此阶段之前确定所有可预测的错误。

5)完成APK的安装
 

 
private void installPackagesLI(List<InstallRequest> requests) {
    ...
    //1.Prepare 准备:分析任何当前安装状态,分析包并对其进行初始验证。
    prepareResult = preparePackageLI(request.args, request.installResult);
    ...
    //2.Scan  扫描:考虑到prepare中收集的上下文,询问已分析的包。
    final List<ScanResult> scanResults = scanPackageTracedLI(
                            prepareResult.packageToScan, prepareResult.parseFlags,
                            prepareResult.scanFlags, System.currentTimeMillis(),
                            request.args.user);
    ...
    //3.Reconcile 调和:在彼此的上下文和当前系统状态中验证扫描的包,以确保安装成功。
    ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs,
            installResults,
            prepareResults,
            mSharedLibraries,
            Collections.unmodifiableMap(mPackages), versionInfos,
            lastStaticSharedLibSettings);
    ...
    //4.Commit 提交:提交所有扫描的包并更新系统状态。这是安装流中唯一可以修改系统状态的地方,必须在此阶段之前确定所有可预测的错误。
    commitPackagesLocked(commitRequest);
    ...
    //5.完成APK的安装
    executePostCommitSteps(commitRequest);
}

安装过程细分为以下15步:

1)首先检查安装包的完整性并解析安装包。

[PackageManagerService.java] preparePackageLI()
// 完整性校验
if (instantApp && onExternal) {
    Slog.i(TAG, "Incompatible ephemeral install; external=" + onExternal);
    throw new PrepareFailure(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
}
 
// 检索包设置,并解析应用
@ParseFlags final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
        | PackageParser.PARSE_ENFORCE_CODE
        | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
 
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);
    DexMetadataHelper.validatePackageDexMetadata(pkg);
} catch (PackageParserException e) {
    throw new PrepareFailure("Failed parse during installPackageLI", e);
} finally {
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

2) 检查SDK版本和沙箱版本,同时检查是否有静态共享库,如有则需要放在内部存储中。

[PackageManagerService.java] preparePackageLI()
 
//检查SDK版本和沙箱版本
if (instantApp) {
    if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
        Slog.w(TAG,
                "Instant app package " + pkg.packageName + " does not target at least O");
        throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                "Instant app package must target at least O");
    }
    if (pkg.mSharedUserId != null) {
        Slog.w(TAG, "Instant app package " + pkg.packageName
                + " may not declare sharedUserId.");
        throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                "Instant app package may not declare a sharedUserId");
    }
}
 
//检查是否有静态共享库
if (pkg.applicationInfo.isStaticSharedLibrary()) {
    // Static shared libraries have synthetic package names
    renameStaticSharedLibraryPackage(pkg);
 
    // No static shared libs on external storage
    if (onExternal) {
        Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
        throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                "Packages declaring static-shared libs cannot be updated");
    }
}

3)检查是否有子安装包,如有则子安装包也需要检测。

[PackageManagerService.java] preparePackageLI()
 
if (pkg.childPackages != null) {
    synchronized (mPackages) {
        final int childCount = pkg.childPackages.size();
        for (int i = 0; i < childCount; i++) {
            PackageParser.Package childPkg = pkg.childPackages.get(i);
            PackageInstalledInfo childRes = new PackageInstalledInfo();
            childRes.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
            childRes.pkg = childPkg;
            childRes.name = childPkg.packageName;
            PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
            if (childPs != null) {
                childRes.origUsers = childPs.queryInstalledUsers(
                        sUserManager.getUserIds(), true);
            }
            if ((mPackages.containsKey(childPkg.packageName))) {
                childRes.removedInfo = new PackageRemovedInfo(this);
                childRes.removedInfo.removedPackage = childPkg.packageName;
                childRes.removedInfo.installerPackageName = childPs.installerPackageName;
            }
            if (res.addedChildPackages == null) {
                res.addedChildPackages = new ArrayMap<>();
            }
            res.addedChildPackages.put(childPkg.packageName, childRes);
        }
    }
}

4)校验安装包签名

[PackageManagerService.java] preparePackageLI()
 
PackageSetting signatureCheckPs = ps;
if (pkg.applicationInfo.isStaticSharedLibrary()) {
    SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(pkg);
    if (libraryInfo != null) {
        signatureCheckPs = mSettings.getPackageLPr(libraryInfo.getPackageName());
    }
}
final KeySetManagerService ksms = mSettings.mKeySetManagerService;
if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
    if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
        throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
                + pkg.packageName + " upgrade keys do not match the "
                + "previously installed version");
    }
}

5)设置相关的权限,包括生成权限、移植权限等

6)如果这是一个系统应用,则检查是否在外部存储上或是是否被其他应用替换等

[PackageManagerService.java] preparePackageLI()
 
if (systemApp) {
    if (onExternal) {
        // Abort update; system app can't be replaced with app on sdcard
        throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                "Cannot install updates to system apps on sdcard");
    } else if (instantApp) {
        // Abort update; system app can't be replaced with an instant app
        throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID,
                "Cannot update a system app with an instant app");
    }
}

7)生成安装包Abi(Application binary interface,应用二进制接口,描述应用程序和操作系统之间或其他应用程序的低级接口)

[PackageManagerService.java] preparePackageLI()
 
try {
    String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ?
            args.abiOverride : pkg.cpuAbiOverride);
    final boolean extractNativeLibs = !pkg.isLibrary();
    derivePackageAbi(pkg, abiOverride, extractNativeLibs);
} catch (PackageManagerException pme) {
    Slog.e(TAG, "Error deriving application ABI", pme);
    throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
            "Error deriving application ABI");
}

8)如有必要,优化dex文件

[PackageManagerService.java] executePostCommitSteps()
 
final boolean performDexopt =
        (!instantApp || Global.getInt(mContext.getContentResolver(),
        Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
        && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);
 
if (performDexopt) {
    // Compile the layout resources.
    if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
        mViewCompiler.compileLayouts(pkg);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
 
    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(packageName,
            REASON_INSTALL,
            DexoptOptions.DEXOPT_BOOT_COMPLETE
                    | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
    mPackageDexOptimizer.performDexOpt(pkg,
            null /* instructionSets */,
            getOrCreateCompilerPackageStats(pkg),
            mDexManager.getPackageUseInfoOrDefault(packageName),
            dexoptOptions);
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

9)冻结APK,并决定是替换安装,还是新安装,组装参数

[PackageManagerService.java] preparePackageLI()
final PackageFreezer freezer =
                freezePackageForInstall(pkgName, installFlags, "installPackageLI");
 
if (replace) {
    //替换安装
 
} else {// new package install
    //安装新的APK
    //1)已安装具有相同名称的包,但已将其重命名为旧名称
    //2)不要允许在同一名称的现有包上安装。
    renamedPackage = mSettings.getRenamedPackageLPr(pkgName1);
}

10)扫描APK,将APK的信息存储在PackageParser.Package类型的newPackage中,一个Package的信息包含了1个base APK以及0个或者多个split APK。

参考上一节的APK扫描:

Android 10.0 PackageManagerService(三)APK扫描-[Android取经之路]

进入 [PackageManagerService.java]  scanPackageTracedLI

调用栈:

scanPackageTracedLI()
        |
scanPackageLI()
        |
parsePackage()

11) 更新共享库

[PackageManagerService.java] commitPackageSettings()
 
synchronized (mPackages) {
    if (!ArrayUtils.isEmpty(reconciledPkg.allowedSharedLibraryInfos)) {
        for (SharedLibraryInfo info : reconciledPkg.allowedSharedLibraryInfos) {
            commitSharedLibraryInfoLocked(info);
        }
        final Map<String, PackageParser.Package> combinedPackages =
                reconciledPkg.getCombinedPackages();
        try {
            // Shared libraries for the package need to be updated.
            updateSharedLibrariesLocked(pkg, null, combinedPackages);
        } catch (PackageManagerException e) {
            Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
        }
        // Update all applications that use this library. Skip when booting
        // since this will be done after all packages are scaned.
        if ((scanFlags & SCAN_BOOTING) == 0) {
            clientLibPkgs = updateAllSharedLibrariesLocked(pkg, combinedPackages);
        }
    }
}

12)更新该APK对应的Settings信息,Settings用于保存所有包的动态设置。

[PackageManagerService.java] commitPackageSettings()
synchronized (mPackages) {
    // Add the new setting to mSettings
    mSettings.insertPackageSettingLPw(pkgSetting, pkg);
    // Add the new setting to mPackages
    mPackages.put(pkg.applicationInfo.packageName, pkg);
}

13) 安装APK,并为新的代码路径准备应用程序配置文件,并再次检查是否需要dex优化

    如果是直接安装新包,会为新的代码路径准备应用程序配置文件

    如果是替换安装:其主要过程为更新设置,清除原有的某些APP数据,重新生成相关的app数据目录等步骤,同时要区分系统应用替换和非系统应用替换。而安装新包:则直接更新设置,生成APP数据即可。
 

[PackageManagerService.java] executePostCommitSteps()
private void executePostCommitSteps(CommitRequest commitRequest) {
    for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
        ...
        //1)进行安装
        prepareAppDataAfterInstallLIF(pkg);
        //2)如果需要替换安装,则需要清楚原有的APP数据
        if (reconciledPkg.prepareResult.clearCodeCache) {
            clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
                    | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
        }
 
 
        //3)为新的代码路径准备应用程序配置文件。这需要在调用dexopt之前完成,以便任何安装时配置文件都可以用于优化。
        mArtManagerService.prepareAppProfiles(
                pkg,
                resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
                /* updateReferenceProfileContent= */ true);
 
 
        final boolean performDexopt =
                (!instantApp || Global.getInt(mContext.getContentResolver(),
                Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
                && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0);
 
        if (performDexopt) {
            ...
            //4)执行dex优化
            mPackageDexOptimizer.performDexOpt(pkg,
                    null /* instructionSets */,
                    getOrCreateCompilerPackageStats(pkg),
                    mDexManager.getPackageUseInfoOrDefault(packageName),
                    dexoptOptions);
        }
 
        BackgroundDexOptService.notifyPackageChanged(packageName);
    }
}

14)APK的安装

[PackageManagerService.java] prepareAppDataAfterInstallLIF()

    通过一系列的调用,最终会调用到[Installer.java] createAppData()进行安装,交给installed进程进行APK的安装

调用栈如下:

prepareAppDataAfterInstallLIF()
    |
prepareAppDataLIF()
    |
prepareAppDataLeafLIF()
    |
[Installer.java]
createAppData()
————————————————
 

private void prepareAppDataAfterInstallLIF(PackageParser.Package pkg) {
    ...
    for (UserInfo user : um.getUsers()) {
        ...
        if (ps.getInstalled(user.id)) {
            // TODO: when user data is locked, mark that we're still dirty
            prepareAppDataLIF(pkg, user.id, flags);
        }
    }
}
 
private void prepareAppDataLIF(PackageParser.Package pkg, int userId, int flags) {
    if (pkg == null) {
        Slog.wtf(TAG, "Package was null!", new Throwable());
        return;
    }
    prepareAppDataLeafLIF(pkg, userId, flags);
    final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
    for (int i = 0; i < childCount; i++) {
        prepareAppDataLeafLIF(pkg.childPackages.get(i), userId, flags);
    }
}
 
private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
    ...
    try {
        // 调用Installd守护进程的入口
        ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                appId, seInfo, app.targetSdkVersion);
    } catch (InstallerException e) {
        if (app.isSystemApp()) {
            destroyAppDataLeafLIF(pkg, userId, flags);
            try {
                ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                        appId, seInfo, app.targetSdkVersion);
            } catch (InstallerException e2) {
                ...
            }
        }
    }
}
[Installer.java]
public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
        String seInfo, int targetSdkVersion) throws InstallerException {
    if (!checkBeforeRemote()) return -1;
    try {
        //mInstalld 为IInstalld的对象,即通过Binder调用到 进程installd,最终调用installd的createAppData()
        //installd的安装过程后面有机会再进行讲解
        return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                targetSdkVersion);
    } catch (Exception e) {
        throw InstallerException.from(e);
    }
}

15)安装完成后,更新设置,更新安装锁等。

 

7 总结
APK的安装主要分为以下4步:

1)将APK的信息通过IO流的形式写入到PackageInstaller.Session中。

2)调用PackageInstaller.Session的commit方法,将APK的信息交由PKMS处理。

3)拷贝APK

4)最后进行安装
 

 

 

 

 

 

 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值