Android PMS缓存刷新机制优化:实现OTA升级后应用缓存更新

前言

在Android设备的OTA(Over-The-Air)升级过程中,有时会遇到应用未能及时更新的问题。具体表现为,升级后新内置应用不出现,或者应用版本未发生变化,需要用户恢复出厂设置才能正常显示新版本。这种情况往往是由于系统缓存未得到正确刷新导致的。为了解决这个问题,本文提供了一种通过修改系统源代码来强制刷新缓存的方法。

PackageManagerService.java

在Android系统的源代码中,PackageManagerService.java是负责应用包管理的核心服务类。
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(PackageManagerServiceInjector injector, boolean factoryTest,
        final String partitionsFingerprint, final boolean isEngBuild,
        final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {
    
    
......

            // Bug 2258844 - add debug log or trace for PKMS(3/6)
            t.traceBegin("prepare package parser cache");
            // 准备包解析器缓存目录,该目录的命名与设备的构建fingerprint有关
            mCacheDir = PackageManagerServiceUtils.preparePackageParserCache(
                    mIsEngBuild, mIsUserDebugBuild, mIncrementalVersion);
            // Bug 2258844 - add debug log or trace for PKMS(4/6)
            t.traceEnd();

......
}

需要注意的是,由于某些国内版本的Android设备在通过GMS(Google Mobile Services)认证后仍然需要修改系统版本信息以避免被谷歌发现,因此这些设备会将构建指纹(fingerprint)锁定。PackageManagerService(PMS)在每次开机时会根据这个指纹值在 /data/system/package_cache 目录下查找对应的缓存目录。在userdebug版本中,这个目录的名称通常为“1”,而在正常版本中,它是通过SystemProperties.digestOf(“ro.build.fingerprint”)生成的。


正常ota升级的话这个值会变,所以会清空之前的缓存,使用新生成的目录,需要做如下特殊操作使系统在升级完ota后去更新缓存目录

修改PackageManagerServiceUtils.java以实现缓存刷新

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

public static @Nullable File preparePackageParserCache(boolean forEngBuild,
            boolean isUserDebugBuild, String incrementalVersion) {
    
    
......

    // The base directory for the package parser cache lives under /data/system/.
    final File cacheBaseDir = Environment.getPackageCacheDirectory();
    if (!FileUtils.createDir(cacheBaseDir)) {
    
    
        return null;
    }

    // There are several items that need to be combined together to safely
    // identify cached items. In particular, changing the value of certain
    // feature flags should cause us to invalidate any caches.
    final String cacheName = FORCE_PACKAGE_PARSED_CACHE_ENABLED ? "debug"
            : SystemProperties.digestOf("ro.build.fingerprint");//文件夹的名称是通过这个生成的

    // Reconcile cache directories, keeping only what we'd actually use.
    for (File cacheDir : FileUtils.listFilesOrEmpty(cacheBaseDir)) {
    
    
        if (Objects.equals(cacheName, cacheDir.getName())) {
    
    //boyin 
        
            if(SystemProperties.get("persist.sys.ota_done","0").equals("1")){
    
    //添加标志位,需要对ota升级应用做修改,在升级成功后把这个标志位置为1
                FileUtils.deleteContentsAndDir(cacheDir);
                SystemProperties.set("persist.sys.ota_done","0");
                Slog.d(TAG, "delete known cache ,升级成功:" + cacheDir.getName());
            }

            Slog.d(TAG, "Keeping known cache " + cacheDir.getName());
        } else {
    
    
            Slog.d(TAG, "Destroying unknown cache " + cacheDir.getName());
            FileUtils.deleteContentsAndDir(cacheDir);
        }
    }

......
}

在这个修改中,我们添加了一个标志位 persist.sys.ota_done 。在OTA升级成功后,我们需要将这个标志位设置为1。然后,在下次系统启动时, PackageManagerServiceUtils.preparePackageParserCache 方法会检查这个标志位。如果标志位为1,它会删除当前的缓存目录及其内容,并重置标志位为0。这样,系统就会使用新的缓存目录,从而确保应用能够得到及时更新。

猜你喜欢

转载自blog.csdn.net/u010345983/article/details/145751882
今日推荐