PackageManagerService Android 8.1 源码解读 05

继续上一篇:PackageManagerService Android 8.1 源码解读 04

这篇主要是讲解apk安装的主要流程代码:
f、点击一个apk后,会弹出【安装界面】,同时显示一个“来历不明的应用......”相关字样的对话框,点击“继续”按钮,执行【PackageInstallerActivity.initiateInstall()】方法;这个方法的主要作用是判断apk是否已经安装

/**
 * Dialog to show when the source of apk can not be identified
 */
public static class AnonymousSourceDialog extends DialogFragment {
    static AnonymousSourceDialog newInstance() {
        return new AnonymousSourceDialog();
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
                .setMessage(R.string.anonymous_source_warning)
                .setPositiveButton(R.string.anonymous_source_continue,
                        ((dialog, which) -> ((PackageInstallerActivity) getActivity())
                                .initiateInstall()))
                .setNegativeButton(R.string.cancel, ((dialog, which) -> getActivity().finish()))
                .create();
    }

    @Override
    public void onCancel(DialogInterface dialog) {
        getActivity().finish();
    }
}

g、【initiateInstall】继续调用【startInstallConfirm】,这里会更新UI, 根据成员变量:mAppInfo是否为空,来加载不同的UI内容;

private void startInstallConfirm() {
    // We might need to show permissions, load layout with permissions
    if (mAppInfo != null) {
        bindUi(R.layout.install_confirm_perm_update, true);
    } else {
        bindUi(R.layout.install_confirm_perm, true);
    }
    .......省略很多代码
}

public void onClick(View v) {
    if (v == mOk) {
        if (mOk.isEnabled()) {
            if (mOkCanInstall || mScrollView == null) {
                if (mSessionId != -1) {
                    mInstaller.setPermissionsResult(mSessionId, true);
                    finish();
                } else {
                    //点击"安装",进行APK安装
                    startInstall();
                }
            } else {
                mScrollView.pageScroll(View.FOCUS_DOWN);
            }
        }
    } else if (v == mCancel) {
        // Cancel and finish
        setResult(RESULT_CANCELED);
        if (mSessionId != -1) {
            //如果mSessionId存在,执行setPermissionsResult()完成取消安装
            mInstaller.setPermissionsResult(mSessionId, false);
        }
        finish();
    }
}

h、【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);
    // 设置包的路径地址:file:///data/user_de/0/com.android.packageinstaller/no_backup/package3012945554531725993.apk 
    newIntent.setData(mPackageURI);
    // 设置目标Activity类:InstallInstalling.class
    newIntent.setClass(this, InstallInstalling.class);
    //下面就是设置Extra的参数了
    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);
    // 启动新的Activity之后,结束掉当前的PackageInstallerActivity
    startActivity(newIntent);
    finish();
}

i、启动 InstallInstalling,进入onCreate, 重点是看onCreate函数中的六步:

@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 {// 安装一个已经存在系统的apk
            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);
        // 第一步.如果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 {
                // 第二步.根据mInstallId向InstallEventReceiver注册一个观察者,
                // launchFinishBasedOnResult会接收到安装事件的回调,
                // 无论安装成功或者失败都会关闭当前的Activity(InstallInstalling)。如果
                // savedInstanceState为null,代码的逻辑也是类似的
                InstallEventReceiver.addObserver(this, mInstallId,
                        this::launchFinishBasedOnResult);
            } catch (EventResultPersister.OutOfIdsException e) {
                // Does not happen
            }
        } else {
            // 第三步.创建SessionParams,它用来代表安装会话的参数,组装params
            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);
            // 第四步.根据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 {
                // 第五步.向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 {
                // 第六步.PackageInstaller的createSession方法内部会通过
                // IPackageInstaller与PackageInstallerService进行进程间通信,
                // 最终调用的是PackageInstallerService的createSession方法来创建并返回
                // mSessionId
                mSessionId = getPackageManager().getPackageInstaller().createSession(params);
            } catch (IOException e) {
                launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
            }
        }

        mCancelButton = (Button) findViewById(R.id.cancel_button);

        mCancelButton.setOnClickListener(view -> {
            if (mInstallingTask != null) {
                mInstallingTask.cancel(true);
            }

            if (mSessionId > 0) {
                getPackageManager().getPackageInstaller().abandonSession(mSessionId);
                mSessionId = 0;
            }

            setResult(RESULT_CANCELED);
            finish();
        });

        mSessionCallback = new InstallSessionCallback();
    }
}

注意: 以上第六步是重点 PackageInstaller 的 createSession()内部会通过【IPackageInstaller】与【PackageInstallerService】进行进程间通信,最终调用的是【PackageInstallerService】的【createSession】方法来【创建并返回】mSessionId


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

@Override
protected void onResume() {
    super.onResume();

    // This is the first onResume in a single life of the activity
    if (mInstallingTask == null) {
        // 获取 PackageInstaller 对象,安装器
        PackageInstaller installer = getPackageManager().getPackageInstaller();
        // 获取sessionInfo
        PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId);

        if (sessionInfo != null && !sessionInfo.isActive()) {
            // 创建任务InstallingAsyncTask对象,最终调用execute方法
            mInstallingTask = new InstallingAsyncTask();
            mInstallingTask.execute();
        } else {
            // we will receive a broadcast when the install is finished
            mCancelButton.setEnabled(false);
            setFinishOnTouchOutside(false);
        }
    }
}

k、Installinstalling.InstallingAsyncTask: 关注 第一步 和 第二步

// 第一步: doInBackground()会根据包(APK)的Uri,将APK的信息通过IO流的形式写入到
// PackageInstaller.Session中
@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 {
        // 创建apk的文件
        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();
        }
    }
}
// 第二步:最后在onPostExecute()中 调用PackageInstaller.Session的commit方法,进行安装
@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 = 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);
        }
    }
}

l、PackageInstaller的commit()方法;

public static class Session implements Closeable {
    private IPackageInstallerSession mSession;
    public void commit(@NonNull IntentSender statusReceiver) {
        try {
            // 通过IPackageInstallerSession来进行进程间的通信,最终会调用
            // PackageInstallerSession的commit方法,这样代码逻辑就到了Java框架层的。
             mSession.commit(statusReceiver, false);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

m、PackageInstallerSession.commit()中,IPackageInstallerSession.aidl接口被PackageInstallerSession继承

// PackageInstallerSession.java类的 commit()

@Override
public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
    Preconditions.checkNotNull(statusReceiver);
    .......
        // 【注意】向Handler发送一个类型为MSG_COMMIT的消息 ,下面会分析
        mCommitted = true;
        mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
    .......
}

MSG_COMMIT在handler中进行处理,进入commitLocked()方法,这个方法比较代码比较多

// PackageInstallerSession.java类

private final PackageManagerService mPm;
private void commitLocked()
        throws PackageManagerException {
    .......省略代码
    mRelinquished = true;
    // 最终调用installStage(),进入PKMG
    mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
            mInstallerPackageName, mInstallerUid, user, mCertificates);
}

n、最终调用 mPm.installStage(),进入PKMS 【经过千辛万苦,终于要进入PKMS了】

void installStage(String packageName, File stagedDir, String stagedCid,
        IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
        String installerPackageName, int installerUid, UserHandle user,
        Certificate[][] certificates) {
    .......省略代码
    // 第一步.创建了类型为INIT_COPY的消息
    final Message msg = mHandler.obtainMessage(INIT_COPY);
    final int installReason = fixUpInstallReason(installerPackageName, installerUid,
            sessionParams.installReason);
    // 第二步.创建InstallParams,它对应于包的安装数据
    final InstallParams params = new InstallParams(origin, null, observer,
            sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
            verificationInfo, user, sessionParams.abiOverride,
            sessionParams.grantedRuntimePermissions, certificates, installReason);
    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));
    // 第三步.将InstallParams通过消息发送出去。
    mHandler.sendMessage(msg);
}
void doHandleMessage(Message msg) {
    switch (msg.what) {
        case INIT_COPY: {
            HandlerParams params = (HandlerParams) msg.obj;
            // 获取挂起的apk安装个数
            int idx = mPendingInstalls.size();
            // 判断是否绑定com.android.defcontainer/.DefaultContainerService服务;
            // 如果没有绑定,进入if体,否则进入else
            if (!mBound) {
                // 连接服务
                if (!connectToService()) {
                    ......
                    //服务连接失败,直接返回
                    return;
                } else {
                    // 绑定到服务后,将处理第一个挂起的请求。
                    mPendingInstalls.add(idx, params);
                }
            } else {
                // 绑定到服务后,将处理第一个挂起的请求。
                mPendingInstalls.add(idx, params);
                if (idx == 0) {
                    mHandler.sendEmptyMessage(MCS_BOUND);
                }
            }
            break;
        }
  ........省略代码
}

static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";

static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
      DEFAULT_CONTAINER_PACKAGE,
      "com.android.defcontainer.DefaultContainerService");
//绑定服务:
private boolean connectToService() {
    if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
            " DefaultContainerService");
    Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
    Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    if (mContext.bindServiceAsUser(service, mDefContainerConn,
            Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        mBound = true;
        return true;
    }
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    return false;
}

o、在服务绑定成功之后,会回调一个函数:

final private DefaultContainerConnection mDefContainerConn =
        new DefaultContainerConnection();
// 绑定服务com.android.defcontainer/.DefaultContainerService,
// 回调onServiceConnected方法;
class DefaultContainerConnection implements ServiceConnection {
    public void onServiceConnected(ComponentName name, IBinder service) {
        if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
        // IMediaContainerService接口不知道做啥用的
        final IMediaContainerService imcs = IMediaContainerService.Stub
                .asInterface(Binder.allowBlocking(service));
        // 发送MCS_BOUND消息给PackageHandler,绑定成功
        mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
    }

    public void onServiceDisconnected(ComponentName name) {
        if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
    }
}
case MCS_BOUND: {
    if (msg.obj != null) {
        // 接受接口对象
        mContainerService = (IMediaContainerService) msg.obj;
    }
    if (mContainerService == null) {
        if (!mBound) {//没有绑定成功
            ......省略,清空安装数据
            mPendingInstalls.clear();
        } else {//继续等待链接服务
            Slog.w(TAG, "Waiting to connect to media container service");
        }
    } else if (mPendingInstalls.size() > 0) {
        HandlerParams params = mPendingInstalls.get(0);
        if (params != null) {
            // 进入队列开始执行拷贝apk的动作
            if (params.startCopy()) {
                .........
        }
    } else {
        // Should never happen ideally.
        Slog.w(TAG, "Empty queue");
    }
    break;
}

p、PKMG的主角开始登场,执行startCopy(),拷贝apk

final boolean startCopy() {
    boolean res;
    try {
        if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);

        if (++mRetries > MAX_RETRIES) {
            // 重试,处理错误
            mHandler.sendEmptyMessage(MCS_GIVE_UP);
            handleServiceError();
            return false;
        } else {
            // 开始处理拷贝
            handleStartCopy();
            res = true;
        }
    } catch (RemoteException e) {
        if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
        mHandler.sendEmptyMessage(MCS_RECONNECT);
        res = false;
    }
    // 处理返回码
    handleReturnCode();
    return res;
}

q、APK 拷贝 方法调用步骤如下:
PKMS->copyApk()->doCopyApk()->DefaultContainerService->copyPacakge()-->copyPackageInner()->copyFile()
// TODO 通过文件流的操作,把APK拷贝到/data/app等目录

public void handleStartCopy() throws RemoteException {
    int ret = PackageManager.INSTALL_SUCCEEDED;
    ......
    final InstallArgs args = createInstallArgs(this);
    ......
    // 拷贝apk
    ret = args.copyApk(mContainerService, true);
    mRet = ret;
}

//开始拷贝apk
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
    try {
        return doCopyApk(imcs, temp);
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}

private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
    if (origin.staged) {
        if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
        codeFile = origin.file;
        resourceFile = origin.file;
        return PackageManager.INSTALL_SUCCEEDED;
    }

    try {
        final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
        //创建代码文件和资源文件
        final File tempDir =
                mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
        codeFile = tempDir;
        resourceFile = tempDir;
    } catch (IOException e) {
        Slog.w(TAG, "Failed to create copy file: " + e);
        return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
    }
		// 新建一个文件描述符,接受数据
    final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
        @Override
        public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
            if (!FileUtils.isValidExtFilename(name)) {
                throw new IllegalArgumentException("Invalid filename: " + name);
            }
            try {
                final File file = new File(codeFile, name);
                final FileDescriptor fd = Os.open(file.getAbsolutePath(),
                        O_RDWR | O_CREAT, 0644);
                Os.chmod(file.getAbsolutePath(), 0644);
                return new ParcelFileDescriptor(fd);
            } catch (ErrnoException e) {
                throw new RemoteException("Failed to open: " + e.getMessage());
            }
        }
    };

    int ret = PackageManager.INSTALL_SUCCEEDED;
    // 通过服务DefaultContainerService,跨进程拷贝apk包
    ret = imcs.copyPackage(origin.file.getAbsolutePath(), target);
    if (ret != PackageManager.INSTALL_SUCCEEDED) {
        Slog.e(TAG, "Failed to copy package");
        return ret;
    }

    final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
    NativeLibraryHelper.Handle handle = null;
    try {
        //拷贝本地库文件
        handle = NativeLibraryHelper.Handle.create(codeFile);
        ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
                abiOverride);
    } catch (IOException e) {
        Slog.e(TAG, "Copying native libraries failed", e);
        ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
    } finally {
        IoUtils.closeQuietly(handle);
    }

    return ret;
}

r、跨进程调用DefaultContainerService服务的copyPackage()方法;-->copyPackageInner()->copyFile()

@Override
public int copyPackage(String packagePath, IParcelFileDescriptorFactory target) {
    if (packagePath == null || target == null) {
        return PackageManager.INSTALL_FAILED_INVALID_URI;
    }

    PackageLite pkg = null;
    try {
        // 创建包文件
        final File packageFile = new File(packagePath);
        // 解析包文件
        pkg = PackageParser.parsePackageLite(packageFile, 0);
        // 内部拷贝包文件
        return copyPackageInner(pkg, target);
    } catch (PackageParserException | IOException | RemoteException e) {
        Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e);
        return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
    }
}

private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)
        throws IOException, RemoteException {
    // 拷贝文件,命名为"base.apk"
    copyFile(pkg.baseCodePath, target, "base.apk");
    if (!ArrayUtils.isEmpty(pkg.splitNames)) {
        for (int i = 0; i < pkg.splitNames.length; i++) {
            copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk");
        }
    }

    return PackageManager.INSTALL_SUCCEEDED;
}

//开始拷贝
private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName)
        throws IOException, RemoteException {
    Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
    InputStream in = null;
    OutputStream out = null;
    try {
        // 创建输入输出流,开始拷贝apk
        in = new FileInputStream(sourcePath);
        out = new ParcelFileDescriptor.AutoCloseOutputStream(
                target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE));
        Streams.copy(in, out);
    } finally {
        IoUtils.closeQuietly(out);
        IoUtils.closeQuietly(in);
    }
}

s、apk拷贝完成之后,再回调handleReturnCode方法,处理返回码,方法调用processPendingInstall()方法

@Override
void handleReturnCode() {
    // If mArgs is null, then MCS couldn't be reached. When it
    // reconnects, it will try again to install. At that point, this
    // will succeed.
    if (mArgs != null) {
        // 处理挂起的安装数据
        processPendingInstall(mArgs, mRet);
    }
}

t、继续走processPendingInstall方法:进入安装apk的核心流程:
 

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
    // 执行一个异步操作,
    mHandler.post(new Runnable() {
        public void run() {
            mHandler.removeCallbacks(this);
             // Result object to be returned
            PackageInstalledInfo res = new PackageInstalledInfo();
            res.setReturnCode(currentStatus);
            res.uid = -1;
            res.pkg = null;
            res.removedInfo = null;
            // 返回码是安装成功的,进入if体
            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                1.如果之前安装失败,清除无用信息
                args.doPreInstall(res.returnCode);
                synchronized (mInstallLock) {
                    // 2. installPackagesTracedLI 是安装过程的核心方法,然后调用
                    // installPackagesLI 进行安装
                    installPackageTracedLI(args, res);
                }
                // 3.如果之前安装失败,清除无用信息
                args.doPostInstall(res.returnCode, res.uid);
            }

            ......
        }
    });
}

private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
    try {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
        // 开始安装apk
        installPackageLI(args, res);
    } finally {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}

x、installPackageLI方法调用真正的安装方法installNewPackageLIF

private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
    .......省略很多代码
    try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
            "installPackageLI")) {
        if (replace) {
            if (pkg.applicationInfo.isStaticSharedLibrary()) {
                // Static libs have a synthetic package name containing the version
                // and cannot be updated as an update would get a new package name,
                // unless this is the exact same version code which is useful for
                // development.
                PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
                if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) {
                    res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
                            + "static-shared libs cannot be updated");
                    return;
                }
            }
            //替换安装apk
            replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
                    installerPackageName, res, args.installReason);
        } else {
            // 开始安装新的apk
            installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
                    args.user, installerPackageName, volumeUuid, res, args.installReason);
        }
    }
    .......省略代码
}
/*
 * Install a non-existing package.
 */
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
        int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
        PackageInstalledInfo res, int installReason) {
    .......
    try {
        // 扫描apk,这个scanPackageTracedLI()方法,之前分析过
        PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
                System.currentTimeMillis(), user);
        // 更新设置信息
        updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
        // 安装成功,准备app的数据,如果安装失败,移除安装的信息
        if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
            // 重点分析这个方法
            prepareAppDataAfterInstallLIF(newPackage);

        } else {
            // Remove package from internal structures, but keep around any
            // data that might have already existed
            deletePackageLIF(pkgName, UserHandle.ALL, false, null,
                    PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
        }
    } catch (PackageManagerException e) {
        res.setError("Package couldn't be installed in " + pkg.codePath, e);
    }

    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

prepareAppDataAfterInstallLIF方法,通过一系列的调用,最终会调用到[Installer.java] createAppData()进行安装,交给installed进程,进行APK的安装
调用栈如下:
prepareAppDataAfterInstallLIF ->
prepareAppDataLIF ->
prepareAppDataLeafLIF->
mInstaller.createAppData

private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
    .......
    // 调用Installd守护进程的入口
    ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                appId, app.seInfo, app.targetSdkVersion);
    ........
}

y、Installer.createAppData 收尾工作,安装完成后,更新设置,更新安装锁等:

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()
        // 【注意】 mInstalld是一个aidl文件,通过此aidl文件调用到 Binder机制的服务
        // 端,服务端那里要操控底层....
        return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                targetSdkVersion);
    } catch (Exception e) {
        throw InstallerException.from(e);
    }
}

z、总结:安装的原理:

APK的安装流程到这里就算完成了;

下一篇将分析 PMS之权限扫描:

PackageManagerService Android 8.1 源码解读 06

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值