Android 如何判断是首次开机?如何判断OTA升级后的首次开机?

Android 如何判断是首次开机?如何判断OTA升级后的首次开机?

 

参考:

http://aosp.opersys.com/xref/android-12.0.0_r2/xref/frameworks/base/services/core/java/com/android/server/am/UserController.java

 

导包:

import android.content.pm.IPackageManager;
import android.app.AppGlobals;
import android.os.RemoteException;

 

        boolean isFirstBootOrUpgrade() {
            IPackageManager pm = AppGlobals.getPackageManager();
            try {
                return pm.isFirstBoot() || pm.isDeviceUpgrading();
            } catch (RemoteException e) {
                // throw e.rethrowFromSystemServer();
            }
        }

 

然后就可以在系统应用里面进行调用了,比如Settings模块就可以获取到是否第一次开机

 

说明:

isFirstBoot() :首次开机
isDeviceUpgrading()) :ota升级后的首次开机

 

 




Android 13 T 源码 (http://aospxref.com/

标记:SCAN_FIRST_BOOT_OR_UPGRADE ,用于标记首次开机或OTA升级后的首次开机

 

1.

http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

    static final int SCAN_NO_DEX = 1 << 0;
    static final int SCAN_UPDATE_SIGNATURE = 1 << 1;
    static final int SCAN_NEW_INSTALL = 1 << 2;
    static final int SCAN_UPDATE_TIME = 1 << 3;
    static final int SCAN_BOOTING = 1 << 4;
    static final int SCAN_REQUIRE_KNOWN = 1 << 7;
    static final int SCAN_MOVE = 1 << 8;
    static final int SCAN_INITIAL = 1 << 9;
    static final int SCAN_DONT_KILL_APP = 1 << 10;
    static final int SCAN_IGNORE_FROZEN = 1 << 11;
    static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1 << 12;
    static final int SCAN_AS_INSTANT_APP = 1 << 13;
    static final int SCAN_AS_FULL_APP = 1 << 14;
    static final int SCAN_AS_VIRTUAL_PRELOAD = 1 << 15;
    static final int SCAN_AS_SYSTEM = 1 << 16;
    static final int SCAN_AS_PRIVILEGED = 1 << 17;
    static final int SCAN_AS_OEM = 1 << 18;
    static final int SCAN_AS_VENDOR = 1 << 19;
    static final int SCAN_AS_PRODUCT = 1 << 20;
    static final int SCAN_AS_SYSTEM_EXT = 1 << 21;
    static final int SCAN_AS_ODM = 1 << 22;
    static final int SCAN_AS_APK_IN_APEX = 1 << 23;
    static final int SCAN_DROP_CACHE = 1 << 24;

OTA升级的判断变量:

private final boolean mIsUpgrade;
    private final boolean mIsPreNUpgrade;
    private final boolean mIsPreNMR1Upgrade;
    private final boolean mIsPreQUpgrade;

......
    
            final VersionInfo ver = mSettings.getInternalVersion();
            mIsUpgrade =
                    !buildFingerprint.equals(ver.fingerprint);
            if (mIsUpgrade) {
                PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from "
                        + ver.fingerprint + " to " + PackagePartitions.FINGERPRINT);
            }

            // when upgrading from pre-M, promote system app permissions from install to runtime
            mPromoteSystemApps =
                    mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

            // When upgrading from pre-N, we need to handle package extraction like first boot,
            // as there is no profiling data available.
            mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;

            mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
            mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;


......
            // If the build fingerprint has changed since the last time we booted,
            // we need to re-grant app permission to catch any new ones that
            // appear.  This is really a hack, and means that apps can in some
            // cases get permissions that the user didn't initially explicitly
            // allow...  it would be nice to have some better way to handle
            // this situation.
            if (mIsUpgrade) {
                Slog.i(TAG, "Build fingerprint changed from " + ver.fingerprint + " to "
                        + PackagePartitions.FINGERPRINT
                        + "; regranting permissions for internal storage");
            }

OTA升级后首次开机打印的log:

Slog.i(TAG, "Build fingerprint changed from " + ver.fingerprint + " to "+ PackagePartitions.FINGERPRINT+ "; regranting permissions for internal storage");

 

 

2.

http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/pm/InitAppsHelper.java

        // Set flag to monitor and not change apk file paths when scanning install directories.
        int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
        if (mIsDeviceUpgrading || mPm.isFirstBoot()) {
            mScanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;   // 扫描apk之前,根据是否首次开机,添加 SCAN_FIRST_BOOT_OR_UPGRADE 标记 
        } else {
            mScanFlags = scanFlags;
        }

 

 // TODO(b/198166813): remove PMS dependency
    InitAppsHelper(PackageManagerService pm, ApexManager apexManager,
            InstallPackageHelper installPackageHelper,
            List<ScanPartition> systemPartitions) {
        mPm = pm;
        mApexManager = apexManager;
        mInstallPackageHelper = installPackageHelper;
        mSystemPartitions = systemPartitions;
        mDirsToScanAsSystem = getSystemScanPartitions();
        mIsDeviceUpgrading = mPm.isDeviceUpgrading();
        mIsOnlyCoreApps = mPm.isOnlyCoreApps();
        // Set flag to monitor and not change apk file paths when scanning install directories.
        int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
        if (mIsDeviceUpgrading || mPm.isFirstBoot()) {
            mScanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
        } else {
            mScanFlags = scanFlags;
        }
        mSystemParseFlags = mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
        mSystemScanFlags = scanFlags | SCAN_AS_SYSTEM;
        mExecutorService = ParallelPackageParser.makeExecutorService();
    }

InitAppsHelper这个工具类 被PKMS服务初始化调用

 

3.

http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/pm/ScanPackageUtils.java

boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;

    public static ScanResult scanPackageOnlyLI(@NonNull ScanRequest request,
            PackageManagerServiceInjector injector,
            boolean isUnderFactoryTest, long currentTime)
            throws PackageManagerException {
        final PackageAbiHelper packageAbiHelper = injector.getAbiHelper();
        ParsedPackage parsedPackage = request.mParsedPackage;
        PackageSetting pkgSetting = request.mPkgSetting;
        final PackageSetting disabledPkgSetting = request.mDisabledPkgSetting;
        final PackageSetting originalPkgSetting = request.mOriginalPkgSetting;
        final @ParsingPackageUtils.ParseFlags int parseFlags = request.mParseFlags;
        final @PackageManagerService.ScanFlags int scanFlags = request.mScanFlags;
        final String realPkgName = request.mRealPkgName;
        final SharedUserSetting oldSharedUserSetting = request.mOldSharedUserSetting;
        final SharedUserSetting sharedUserSetting = request.mSharedUserSetting;
        final UserHandle user = request.mUser;
        final boolean isPlatformPackage = request.mIsPlatformPackage;

        List<String> changedAbiCodePath = null;

        if (DEBUG_PACKAGE_SCANNING) {
            if ((parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0) {
                Log.d(TAG, "Scanning package " + parsedPackage.getPackageName());
            }
        }

        // Initialize package source and resource directories
        final File destCodeFile = new File(parsedPackage.getPath());

        // We keep references to the derived CPU Abis from settings in oder to reuse
        // them in the case where we're not upgrading or booting for the first time.
        String primaryCpuAbiFromSettings = null;
        String secondaryCpuAbiFromSettings = null;
        boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;
        if (!needToDeriveAbi) {
            if (pkgSetting != null) {
                // TODO(b/154610922): if it is not first boot or upgrade, we should directly use
                // API info from existing package setting. However, stub packages currently do not
                // preserve ABI info, thus the special condition check here. Remove the special
                // check after we fix the stub generation.
                if (pkgSetting.getPkg() != null && pkgSetting.getPkg().isStub()) {
                    needToDeriveAbi = true;
                } else {
                    primaryCpuAbiFromSettings = pkgSetting.getPrimaryCpuAbi();
                    secondaryCpuAbiFromSettings = pkgSetting.getSecondaryCpuAbi();
                }
            } else {
                // Re-scanning a system package after uninstalling updates; need to derive ABI
                needToDeriveAbi = true;
            }
        }
    
    
        ......
    }

ScanPackageUtils 这个工具类被 InstallPackageHelper.java 调用

 

4.

 

http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java

处理apk的so库路径

  private static NativeLibraryPaths deriveNativeLibraryPaths(final Abis abis,
            final File appLib32InstallDir, final String codePath, final String sourceDir,
            final boolean isSystemApp, final boolean isUpdatedSystemApp) {
        final File codeFile = new File(codePath);
        final boolean bundledApp = isSystemApp && !isUpdatedSystemApp;

        final String nativeLibraryRootDir;
        final boolean nativeLibraryRootRequiresIsa;
        final String nativeLibraryDir;
        final String secondaryNativeLibraryDir;

        if (isApkFile(codeFile)) {
            // Monolithic install
            if (bundledApp) {
                // If "/system/lib64/apkname" exists, assume that is the per-package
                // native library directory to use; otherwise use "/system/lib/apkname".
                final String apkRoot = calculateBundledApkRoot(sourceDir);
                final boolean is64Bit = VMRuntime.is64BitInstructionSet(
                        getPrimaryInstructionSet(abis));

                // This is a bundled system app so choose the path based on the ABI.
                // if it's a 64 bit abi, use lib64 otherwise use lib32. Note that this
                // is just the default path.
                final String apkName = deriveCodePathName(codePath);
                final String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME;
                nativeLibraryRootDir = Environment.buildPath(new File(apkRoot), libDir,
                        apkName).getAbsolutePath();

                if (abis.secondary != null) {
                    final String secondaryLibDir = is64Bit ? LIB_DIR_NAME : LIB64_DIR_NAME;
                    secondaryNativeLibraryDir = Environment.buildPath(new File(apkRoot),
                            secondaryLibDir, apkName).getAbsolutePath();
                } else {
                    secondaryNativeLibraryDir = null;
                }
            } else {
                final String apkName = deriveCodePathName(codePath);
                nativeLibraryRootDir = new File(appLib32InstallDir, apkName)
                        .getAbsolutePath();
                secondaryNativeLibraryDir = null;
            }

            nativeLibraryRootRequiresIsa = false;
            nativeLibraryDir = nativeLibraryRootDir;
        } else {
            // Cluster install
            nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath();
            nativeLibraryRootRequiresIsa = true;

            nativeLibraryDir = new File(nativeLibraryRootDir,
                    getPrimaryInstructionSet(abis)).getAbsolutePath();

            if (abis.secondary != null) {
                secondaryNativeLibraryDir = new File(nativeLibraryRootDir,
                        VMRuntime.getInstructionSet(abis.secondary)).getAbsolutePath();
            } else {
                secondaryNativeLibraryDir = null;
            }
        }
        return new NativeLibraryPaths(nativeLibraryRootDir, nativeLibraryRootRequiresIsa,
                nativeLibraryDir, secondaryNativeLibraryDir);
    }

 

posted @ 2022-08-15 16:12  行走的思想  阅读(26)  评论(0)    收藏  举报