android 12 adb安装apk 安卓adb安装_android


image.png


目录

Android apk安装流程之adb安装

app安装方式

Android应用程序安装有四种方式:

  1. 系统启动时安装,没有安装界面
  2. 第三方应用安装,有安装界面,也是我们最熟悉的方式
  3. ADB命令安装,没有安装界面
  4. 通过Google Play市场安装,没有安装界面

四种方式最后都是通过PackageManagerService服务来完成应用程序的安装。

PackageManagerService服务通过与Installd服务通信,发送具体的指令来执行应用程序的安装、卸载等工作。


android 12 adb安装apk 安卓adb安装_android 12 adb安装apk_02


image.png


使用路径

app在安装时涉及到如下几个重要目录:

目录

解释

system/app

系统应用程序的目录

data/app

用户程序安装的目录

data/data

存放应用程序数据的目录

data/dalvik-cache

存放的是经过优化的dex文件

APK文件结构

目录

描述

assert

存放的原生资源文件,通过AssetManager类访问

lib

native库文件

META-INF

存放签名信息,用来保证APK包的完整性和系统的安全。系统安装APK时,应用管理器会按照对应算法对包里文件做校验,如果校验结果与META-INF中内容不一致,则不会安装这个APK。

res

种资源文件系统会在R.java里面自动生成该资源文件的ID,所以访问这种资源文件比较简单,通过R.XXX.ID即可

AndroidManifest.xml

每个应用都必须定义和包含,描述应用的名字、版本权限、引用的库文件等信息。apk中的AndroidManifest.xml经过压缩,可以通过AXMLPrinter2工具解开。

classes.dex

是JAVA源码编译后生成的JAVA字节码文件。但Android使用的dalvik虚拟机与标准的JAVA虚拟机不兼容,dex文件与class文件相比,不论是文件结构还是opcode都不一样。

resources.arsc

编译后的二进制资源文件。

应用程序安装过程

  1. adb install:
    安装入口函数为Pm.runInstall
    frameworks\base\cmds\pm\src\com\android\commands\pm\Pm.java
  2. 网络下载应用安装和第三方应用安装:
    安装入口函数为ApplicationPackageManager.installPackage
    frameworks\base\core\java\android\app\ApplicationPackageManager.java

apk安装的四大步骤:1. 拷贝apk到指定的目录:默认情况下,用户安装的apk首先会拷贝到/data/app下,用户有访问/data/app目录的权限,但系统出厂的apk文件会被放到/system分区下,包括/system/app,/system/vendor/app,以及/system/priv-app等,该分区需要root权限的用户才能访问。2. 加载apk、拷贝文件、创建应用的数据目录:为了加快APP的启动速度,apk在安装的时候,会首先将APP的可执行文件(dex)拷贝到/data/dalvik-cache目录下,缓存起来。再在/data/data/目录下创建应用程序的数据目录(以应用包名命令),用来存放应用的数据库、xml文件、cache、二进制的so动态库等。3. 解析apk的AndroidManifest.xml文件:在安装apk的过程中,会解析apk的AndroidManifest.xml文件,将apk的权限、应用包名、apk的安装位置、版本、userID等重要信息保存在/data/system/packages.xml文件中。这些操作都是在PackageManagerService中完成的。4. 显示icon图标:应用程序经过PMS中的逻辑处理后,相当于已经注册好了,如果想要在Android桌面上看到icon图标,则需要Launcher将系统中已经安装的程序展现在桌面上。

adb install 的安装方式

adb install 的安装方式,会调用| commandline.cpp |
中的adb_commandline函数:

int adb_commandline(int argc, const char** argv) {
    ……
    else if (!strcmp(argv[0], "install")) {
        if (argc < 2) return usage("install requires an argument");
        if (_use_legacy_install()) {
            return install_app_legacy(transport_type, serial, argc, argv);
        }
        return install_app(transport_type, serial, argc, argv);
    }
    ……
    return 1;
}

adb会把apk文件copy到data/local/tmp/目录下,然后向shell服务发送pm命令安装apk,最后调用Pm.runInstall()方法来安装apk。

static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
    static const char *const DATA_DEST = "/data/local/tmp/%s";
    static const char *const SD_DEST = "/sdcard/tmp/%s";
    const char* where = DATA_DEST;
    
    ……
    int result = -1;
    std::vector<const char*> apk_file = {argv[last_apk]};
    std::string apk_dest = android::base::StringPrintf(
        where, android::base::Basename(argv[last_apk]).c_str());
    // 复制app到/data/local/tmp/下
    if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
    argv[last_apk] = apk_dest.c_str(); 
    //执行pm命令
    result = pm_command(transport, serial, argc, argv);

cleanup_apk:
    delete_file(transport, serial, apk_dest);
    return result;
}

最后进入到Pm.runInstall()函数来安装apk。

Pm.java中的runInstall函数:

private int runInstall() throws RemoteException {
        long startedTime = SystemClock.elapsedRealtime();
        final InstallParams params = makeInstallParams();
        final String inPath = nextArg();
        if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
            File file = new File(inPath);
            if (file.isFile()) {
                try {
                    // 使用PackageParser解析apk包
                    ApkLite baseApk = PackageParser.parseApkLite(file, 0);
                    PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
                            null, null);
                    params.sessionParams.setSize(
                            PackageHelper.calculateInstalledSize(pkgLite, false,
                            params.sessionParams.abiOverride));
                } catch (PackageParserException | IOException e) {
                    System.err.println("Error: Failed to parse APK file: " + e);
                    return 1;
                }
            } else {
                System.err.println("Error: Can't open non-file: " + inPath);
                return 1;
            }
        }

        // 创建Session
        final int sessionId = doCreateSession(params.sessionParams,
                params.installerPackageName, params.userId);

        try {
            if (inPath == null && params.sessionParams.sizeBytes == -1) {
                System.err.println("Error: must either specify a package size or an APK file");
                return 1;
            }

            // 写入Session
            if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
                    false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
                return 1;
            }

            // 提交Session
            Pair<String, Integer> status = doCommitSession(sessionId, false /*logSuccess*/);
            if (status.second != PackageInstaller.STATUS_SUCCESS) {
                return 1;
            }
            Log.i(TAG, "Package " + status.first + " installed in " + (SystemClock.elapsedRealtime()
                    - startedTime) + " ms");
            System.out.println("Success");
            return 0;
        } finally {
            try {
                mInstaller.abandonSession(sessionId);
            } catch (Exception ignore) {
            }
        }
    }

runInstall主要进行了三件事,创建session、对session进行写操作,最后提交session。

doCreateSession函数调用的是PackageInstallerService的createSession,这个过程主要是为APK安装做好准备工作,例如权限检查、目的临时文件的创建等, 最终创建出PackageInstallerSession对象。

PackageInstallerSession可以看做是”安装APK”这个请求的封装,其中包含了处理这个请求需要的一些信息。实际上PackageInstallerSession不仅是分装请求的对象,其自身还是个服务端。
doCreateSession函数:

private int doCreateSession(SessionParams params, String installerPackageName, int userId)
            throws RemoteException {
        userId = translateUserId(userId, "runInstallCreate");
        if (userId == UserHandle.USER_ALL) {
            userId = UserHandle.USER_SYSTEM;
            params.installFlags |= PackageManager.INSTALL_ALL_USERS;
        }

        final int sessionId = mInstaller.createSession(params, installerPackageName, userId);
        return sessionId;
    }

mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));

mInstaller = mPm.getPackageInstaller();

进入PackageManagerService.java类看一下getPackageInstaller函数:

public IPackageInstaller getPackageInstaller() {
        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
            return null;
        }
        return mInstallerService;
    }

    final PackageInstallerService mInstallerService;

    mInstallerService = new PackageInstallerService(context, this);

所以最后获取了PackageInstallerService对象,并执行createSession函数:

public int createSession(SessionParams params, String installerPackageName, int userId) {
        try {
            return createSessionInternal(params, installerPackageName, userId);
        } catch (IOException e) {
            throw ExceptionUtils.wrap(e);
        }
    }

    private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
            throws IOException {
        // 权限检查
        final int callingUid = Binder.getCallingUid();
        mPm.enforceCrossUserPermission(callingUid, userId, true, true, "createSession");

        if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
            throw new SecurityException("User restriction prevents installing");
        }
        
        ……

        // 获取图标数据
        if (params.appIcon != null) {
            final ActivityManager am = (ActivityManager) mContext.getSystemService(
                    Context.ACTIVITY_SERVICE);
            final int iconSize = am.getLauncherLargeIconSize();
            if ((params.appIcon.getWidth() > iconSize * 2)
                    || (params.appIcon.getHeight() > iconSize * 2)) {
                params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,
                        true);
            }
        }
        ……

        final long createdMillis = System.currentTimeMillis();
        //创建文件夹
        File stageDir = null;
        String stageCid = null;
        if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
            final boolean isInstant =
                    (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
            stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
        } else {
            stageCid = buildExternalStageCid(sessionId);
        }

        // 创建session
        session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
                mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
                params, createdMillis, stageDir, stageCid, false, false);

        synchronized (mSessions) {
            mSessions.put(sessionId, session);
        }

        mCallbacks.notifySessionCreated(session.sessionId, session.userId);
        writeSessionsAsync();
        return sessionId;
    }

之后开始进入doWriteSession函数:

private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
            boolean logSuccess) throws RemoteException {
        if (STDIN_PATH.equals(inPath)) {
            inPath = null;
        } else if (inPath != null) {
            final File file = new File(inPath);
            if (file.isFile()) {
                sizeBytes = file.length();
            }
        }

        final SessionInfo info = mInstaller.getSessionInfo(sessionId);

        PackageInstaller.Session session = null;
        InputStream in = null;
        OutputStream out = null;
        try {
            session = new PackageInstaller.Session(
                    mInstaller.openSession(sessionId));

            if (inPath != null) {
                in = new FileInputStream(inPath);
            } else {
                in = new SizedInputStream(System.in, sizeBytes);
            }
            out = session.openWrite(splitName, 0, sizeBytes);

            int total = 0;
            byte[] buffer = new byte[65536];
            int c;
            while ((c = in.read(buffer)) != -1) {
                total += c;
                out.write(buffer, 0, c);

                if (info.sizeBytes > 0) {
                    final float fraction = ((float) c / (float) info.sizeBytes);
                    session.addProgress(fraction);
                }
            }
            session.fsync(out);

            if (logSuccess) {
                System.out.println("Success: streamed " + total + " bytes");
            }
            return PackageInstaller.STATUS_SUCCESS;
        } catch (IOException e) {
            System.err.println("Error: failed to write; " + e.getMessage());
            return PackageInstaller.STATUS_FAILURE;
        } finally {
            IoUtils.closeQuietly(out);
            IoUtils.closeQuietly(in);
            IoUtils.closeQuietly(session);
        }
    }

该函数通过PackageInstallerSession将/data/local/tmp的apk拷贝到终端目录内

最后开始执行doCommitSession函数:

private Pair<String, Integer> doCommitSession(int sessionId, boolean logSuccess)
            throws RemoteException {
        PackageInstaller.Session session = null;
        try {
            // 获取session
            session = new PackageInstaller.Session(
                    mInstaller.openSession(sessionId));

            final LocalIntentReceiver receiver = new LocalIntentReceiver();
            // 执行session的commit函数
            session.commit(receiver.getIntentSender());

            final Intent result = receiver.getResult();
            final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
                    PackageInstaller.STATUS_FAILURE);
            if (status == PackageInstaller.STATUS_SUCCESS) {
                if (logSuccess) {
                    System.out.println("Success");
                }
            } else {
                System.err.println("Failure ["
                        + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
            }
            return new Pair<>(result.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME), status);
        } finally {
            IoUtils.closeQuietly(session);
        }
    }

跟踪下PackageInstaller.java中的session的commit函数:

public static class Session implements Closeable {
        private IPackageInstallerSession mSession;

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

    }

执行进入PackageInstallerSession.java类中的commit函数:

public void commit(IntentSender statusReceiver) {
        Preconditions.checkNotNull(statusReceiver);

        final boolean wasSealed;
        synchronized (mLock) {
            wasSealed = mSealed;
            if (!mSealed) {
                for (RevocableFileDescriptor fd : mFds) {
                    if (!fd.isRevoked()) {
                        throw new SecurityException("Files still open");
                    }
                }
                for (FileBridge bridge : mBridges) {
                    if (!bridge.isClosed()) {
                        throw new SecurityException("Files still open");
                    }
                }
                mSealed = true;
            }
            mClientProgress = 1f;
            computeProgressLocked(true);
        }

        if (!wasSealed) {
            mCallback.onSessionSealedBlocking(this);
        }

        mActiveCount.incrementAndGet();

        final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
                statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);
        mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
    }

函数中发送消息MSG_COMMIT:

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, 0, 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;
            }
        }
    };

之后执行了commitLocked函数:

private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
            throws PackageManagerException {
        ……
        try {
            resolveStageDir();
        } catch (IOException e) {
            throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
                    "Failed to resolve stage location", e);
        }

        // 验证app是否正常
        validateInstallLocked(pkgInfo, appInfo);

        Preconditions.checkNotNull(mPackageName);
        Preconditions.checkNotNull(mSignatures);
        Preconditions.checkNotNull(mResolvedBaseFile);

        if (!mPermissionsAccepted) {
            // 安装权限获得
            final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
            intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
            intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
            try {
                mRemoteObserver.onUserActionRequired(intent);
            } catch (RemoteException ignored) {
            }

            close();
            return;
        }
        ……

        if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
            try {
                final List<File> fromFiles = mResolvedInheritedFiles;
                final File toDir = resolveStageDir();

                if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
                if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
                    throw new IllegalStateException("mInheritedFilesBase == null");
                }

                if (isLinkPossible(fromFiles, toDir)) {
                    if (!mResolvedInstructionSets.isEmpty()) {
                        final File oatDir = new File(toDir, "oat");
                        // 创建oat文件夹
                        createOatDirs(mResolvedInstructionSets, oatDir);
                    }
                    linkFiles(fromFiles, toDir, mInheritedFilesBase);
                } else {
                    copyFiles(fromFiles, toDir);
                }
            } catch (IOException e) {
                throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                        "Failed to inherit existing install", e);
            }
        }

        mInternalProgress = 0.5f;
        computeProgressLocked(true);

        // 解压native动态库
        extractNativeLibraries(mResolvedStageDir, params.abiOverride);、
        ……
        final UserHandle user;
        if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
            user = UserHandle.ALL;
        } else {
            user = new UserHandle(userId);
        }

        mRelinquished = true;
        // 开始真正的安装
        mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
                installerPackageName, installerUid, user, mCertificates);
    }

最后执行了PackageManagerService.java的installStage函数:

void installStage(String packageName, File stagedDir, String stagedCid,
            IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
            String installerPackageName, int installerUid, UserHandle user,
            Certificate[][] certificates) {
        ……
        final VerificationInfo verificationInfo = new VerificationInfo(
                sessionParams.originatingUri, sessionParams.referrerUri,
                sessionParams.originatingUid, installerUid);

        final OriginInfo origin;
        if (stagedDir != null) {
            origin = OriginInfo.fromStagedFile(stagedDir);
        } else {
            origin = OriginInfo.fromStagedContainer(stagedCid);
        }

        // 发送INIT_COPY信息
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        final int installReason = fixUpInstallReason(installerPackageName, installerUid,
                sessionParams.installReason);
        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));

        mHandler.sendMessage(msg);
    }

其中发送了INIT_COPY信息:

final ArrayList<HandlerParams> mPendingInstalls =
            new ArrayList<HandlerParams>();

                   case INIT_COPY: {
                    // 这里取出的其实就是InstallParams
                    HandlerParams params = (HandlerParams) msg.obj;
                    //idx为当前等待处理处理的安装请求的个数
                    int idx = mPendingInstalls.size();
                    if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
                    //初始时,mBound的值为false
                    if (!mBound) {
                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                        //连接安装服务
                        if (!connectToService()) {
                             ……
                        } else {
                            //绑定服务成功后,将新的请求加入到mPendingIntalls中,等待处理
                            mPendingInstalls.add(idx, params);
                        }
                    } else {
                        //如果是第一个请求,则直接发送事件MCS_BOUND,触发处理流程
                        mPendingInstalls.add(idx, params);
                        if (idx == 0) {
                            mHandler.sendEmptyMessage(MCS_BOUND);
                        }
                    }
                    break;
                }

INIT_COPY最后会发送MCS_BOUND消息触发接下来的流程:

case MCS_BOUND: {
                    if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
                    if (msg.obj != null) {
                        mContainerService = (IMediaContainerService) msg.obj;
                        Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "bindingMCS",
                                System.identityHashCode(mHandler));
                    }
                    if (mContainerService == null) {
                        ……
                    } else if (mPendingInstalls.size() > 0) {
                        HandlerParams params = mPendingInstalls.get(0);
                        if (params != null) {
                            ……
                            if (params.startCopy()) {
                                if (DEBUG_SD_INSTALL) Log.i(TAG,
                                        "Checking for more work or unbind...");
                                // 从读了中删除
                                if (mPendingInstalls.size() > 0) {
                                    mPendingInstalls.remove(0);
                                }
                                if (mPendingInstalls.size() == 0) {
                                    ……
                                } else {
                                    if (DEBUG_SD_INSTALL) Log.i(TAG,
                                            "Posting MCS_BOUND for next work");
                                    mHandler.sendEmptyMessage(MCS_BOUND);
                                }
                            }
                            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                        }
                    } else {
                        Slog.w(TAG, "Empty queue");
                    }
                    break;
                }

代码中看主要执行了HandlerParams中的startCopy函数,也是在文件PackageManagerService.java中:

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

                if (++mRetries > MAX_RETRIES) {
                    Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
                    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;
        }

继`续执行handleStartCopy函数:

public void handleStartCopy() throws RemoteException {
            int ret = PackageManager.INSTALL_SUCCEEDED;
            // 决定是安装在手机内还是sdcard中,设置对应标志位
            if (origin.staged) {
                if (origin.file != null) {
                    installFlags |= PackageManager.INSTALL_INTERNAL;
                    installFlags &= ~PackageManager.INSTALL_EXTERNAL;
                } else if (origin.cid != null) {
                    installFlags |= PackageManager.INSTALL_EXTERNAL;
                    installFlags &= ~PackageManager.INSTALL_INTERNAL;
                } else {
                    throw new IllegalStateException("Invalid stage location");
                }
            }
            ……
            // 检查APK的安装位置是否正确
            if (onInt && onSd) {
                // Check if both bits are set.
                Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
                ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
            } else if (onSd && ephemeral) {
                Slog.w(TAG,  "Conflicting flags specified for installing ephemeral on external");
                ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
            } else {
                pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
                        packageAbiOverride);

                if (DEBUG_EPHEMERAL && ephemeral) {
                    Slog.v(TAG, "pkgLite for install: " + pkgLite);
                }
                if (!origin.staged && pkgLite.recommendedInstallLocation
                        == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
                    final StorageManager storage = StorageManager.from(mContext);
                    final long lowThreshold = storage.getStorageLowBytes(
                            Environment.getDataDirectory());

                    final long sizeBytes = mContainerService.calculateInstalledSize(
                            origin.resolvedPath, isForwardLocked(), packageAbiOverride);

                    try {
                        mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
                        pkgLite = mContainerService.getMinimalPackageInfo(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;
                    }
                }
            }

            ……
            // createInstallArgs用于创建一个安装参数对象
            final InstallArgs args = createInstallArgs(this);
            mArgs = args;


            ……
                    // 调用InstallArgs的copyApk函数
                    ret = args.copyApk(mContainerService, true);
            ……      
            mRet = ret;
        }

handleStartCopy主要功能是获取安装位置信息以及复制apk到指定位置。

InstallArgs中的copyApk负责复制APK文件,具体实现在子类FileInstallArgs和MoveInstallArgs里面:

private InstallArgs createInstallArgs(InstallParams params) {
        if (params.move != null) {
            return new MoveInstallArgs(params);
        } else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
            return new AsecInstallArgs(params);
        } else {
            return new FileInstallArgs(params);
        }
    }

继续看下startCopy中的handleReturnCode函数:

void handleReturnCode() {
            if (mArgs != null) {
                processPendingInstall(mArgs, mRet);
            }
        }

主要的安装流程都在processPendingInstall函数:

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
  
                PackageInstalledInfo res = new PackageInstalledInfo();
                res.setReturnCode(currentStatus);
                res.uid = -1;
                res.pkg = null;
                res.removedInfo = null;
                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                    //1、预安装,检查包状态,确保环境ok,如果环境不ok,那么会清理拷贝的文件
                    args.doPreInstall(res.returnCode);
                    synchronized (mInstallLock) {
                        //2、安装,调用installPackageTracedLI进行安装
                        installPackageTracedLI(args, res);
                    }
                    //3、安装收尾
                    args.doPostInstall(res.returnCode, res.uid);
                }

                ……

                if (!doRestore) {
                    // No restore possible, or the Backup Manager was mysteriously not
                    // available -- just fire the post-install work request directly.
                    if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);

                    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
                    //4、生成一个POST_INSTALL消息给PackageHanlder
                    Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
                    mHandler.sendMessage(msg);
                }
            }
        });
    }

看一下installPackageTracedLI函数:

private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo res) {
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
            installPackageLI(args, res);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }

继续跟踪installPackageLI函数:

private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
        ……
        // PackageParser对象
        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 {
            // 开始解析package
            pkg = pp.parsePackage(tmpPackageFile, parseFlags);
        } catch (PackageParserException e) {
            res.setError("Failed parse during installPackageLI", e);
            return;
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
        
        if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
            Slog.w(TAG, "Instant app package " + pkg.packageName + " does not target O");
            res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
                    "Instant app package must target O");
            return;
        }
        if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) {
            Slog.w(TAG, "Instant app package " + pkg.packageName
                    + " does not target targetSandboxVersion 2");
            res.setError(INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
                    "Instant app package must use targetSanboxVersion 2");
            return;
        }

        if (pkg.applicationInfo.isStaticSharedLibrary()) {
            // 静态库
            renameStaticSharedLibraryPackage(pkg);

            // No static shared libs on external storage
            if (onExternal) {
                Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
                res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                        "Packages declaring static-shared libs cannot be updated");
                return;
            }
        }


        try {
            //2. 加载证书,获取签名信息
            if (args.certificates != null) {
                try {
                    PackageParser.populateCertificates(pkg, args.certificates);
                } catch (PackageParserException e) {
                    PackageParser.collectCertificates(pkg, parseFlags);
                }
            } else {
                PackageParser.collectCertificates(pkg, parseFlags);
            }
        } catch (PackageParserException e) {
            res.setError("Failed collect during installPackageLI", e);
            return;
        }


        pp = null;
        String oldCodePath = null;
        boolean systemApp = false;
        synchronized (mPackages) {
            // 3.检测packages是否已经存在
            if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
                String oldName = mSettings.getRenamedPackageLPr(pkgName);
                if (pkg.mOriginalPackages != null
                        && pkg.mOriginalPackages.contains(oldName)
                        && mPackages.containsKey(oldName)) {
                    pkg.setPackageName(oldName);
                    pkgName = pkg.packageName;
                    replace = true;
                    if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
                            + oldName + " pkgName=" + pkgName);
                } else if (mPackages.containsKey(pkgName)) {
                    replace = true;
                    if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
                }
                ……

                if (replace) {
                     // 4.更新已经存在的packages
                    PackageParser.Package oldPackage = mPackages.get(pkgName);
                    final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion;
                    final int newTargetSdk = pkg.applicationInfo.targetSdkVersion;
                    if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
                            && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
                        res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE,
                                "Package " + pkg.packageName + " new target SDK " + newTargetSdk
                                        + " doesn't support runtime permissions but the old"
                                        + " target SDK " + oldTargetSdk + " does.");
                        return;
                    }
                    final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion;
                    final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion;
                    if (oldTargetSandbox == 2 && newTargetSandbox != 2) {
                        res.setError(PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
                                "Package " + pkg.packageName + " new target sandbox "
                                + newTargetSandbox + " is incompatible with the previous value of"
                                + oldTargetSandbox + ".");
                        return;
                    }

                    if (oldPackage.parentPackage != null) {
                        res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                                "Package " + pkg.packageName + " is child of package "
                                        + oldPackage.parentPackage + ". Child packages "
                                        + "can be updated only through the parent package.");
                        return;
                    }
                }
            }
        ……

        startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);

        try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
                "installPackageLI")) {
            if (replace) {
                if (pkg.applicationInfo.isStaticSharedLibrary()) {
                    // 4.更新已经存在的packages
                    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;
                    }
                }
                replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
                        installerPackageName, res, args.installReason);
            } else {
                // 5.安装新的packages
                installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
                        args.user, installerPackageName, volumeUuid, res, args.installReason);
            }
        }
        ……
    }

这一段代码比较多,主要解析APK的AndroidManifest.xml,将每个标签对应的信息添加到Package的相关列表中,如将下的信息添加到Package的activities列表等。

  1. 加载apk证书,获取签名信息
  2. 检查目前安装的APK是否在系统中已存在:
    已存在,则调用replacePackageLIF进行替换安装。
    不存在,否则调用installNewPackageLIF进行安装。

继续看一下installNewPackageLIF函数:

private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
            int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
            PackageInstalledInfo res, int installReason) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");

        String pkgName = pkg.packageName;

        if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);

        synchronized(mPackages) {
            final String renamedPackage = mSettings.getRenamedPackageLPr(pkgName);
            if (renamedPackage != null) {
                res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                        + " without first uninstalling package running as "
                        + renamedPackage);
                return;
            }
            if (mPackages.containsKey(pkgName)) {
                // Don't allow installation over an existing package with the same name.
                res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
                        + " without first uninstalling.");
                return;
            }
        }

        try {
            // 1. 安装apk
            PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
                    System.currentTimeMillis(), user);

            // 更新set
            updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);

            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);
    }

scanPackageTracedL函数最后会安装apk:

private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]");
        try {
            return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }

继续执行scanPackageLI:

private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
            int scanFlags, long currentTime, @Nullable UserHandle user)
                    throws PackageManagerException {
        boolean success = false;
        try {
            final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
                    currentTime, user);
            success = true;
            return res;
        } finally {
            if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
                // DELETE_DATA_ON_FAILURES is only used by frozen paths
                destroyAppDataLIF(pkg, UserHandle.USER_ALL,
                        StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
                destroyAppProfilesLIF(pkg, UserHandle.USER_ALL);
            }
        }
    }

scanPackageDirtyLI是apk安装的核心部分,下一篇文章继续介绍下。

到这里基本上安装就结束了。接下来看下流程图:


android 12 adb安装apk 安卓adb安装_android 12 adb安装apk_03


22.png


android 12 adb安装apk 安卓adb安装_hadoop_04


image.png