问题:客户反馈内置的应用升级成功后立刻断电重启,应用的版本被恢复。

使用adb命令升级客户应用,查看版本显示已更新,/data/system目录下packages.xmlpackages.xml中应用版本信息均已更新

C:\Users\dell>adb shell dumpsys package com.xxx.xxx | findstr version
    versionCode=85 minSdk=21 targetSdk=28
    versionName=1.0.1.0
    signatures=PackageSignatures{d02434f version:2, signatures:[b414bf3f], past signatures:[]}
    versionCode=6 minSdk=21 targetSdk=28
    versionName=1.0.0.5
    signatures=PackageSignatures{9ec2ba version:0, signatures:[], past signatures:[]}

C:\Users\dell>

立刻断电重启,结果是应用版本恢复为升级前,packages.xmlpackages.xml中应用版本也恢复为升级前。
抓取开机时的部分log

D PackageManager: Scanning app dir /system/app scanFlags=66064 flags=0x10
D PackageParser2: Parse times for '/system/app/Huaxinan': parse=103ms, update_cache=16 ms
D PackageManager: updatedPkg = PackageSetting{dd36952 com.hxa.liquorDetection/10072}
W PackageManager: Failed to scan /system/app/Huaxinan: Package com.hxa.liquorDetection at /system/app/Huaxinan ignored: updated version 85 better than this 6
D PackageParsing: Scanning base APK: /system/app/SimAppDialog/SimAppDialog.apk
...
D PackageManager: Scanning app dir /data/app scanFlags=656 flags=0x0
D ziparchive: Zip: EOCD not found, /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw==/base.apk is not zip
E system_server: Failed to open APK '/data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw==/base.apk' Invalid file
W PackageManager: Failed to parse /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==: Failed to parse /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw==/base.apk
W PackageManager: Deleting invalid package at /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==
D PackageParsing: Scanning base APK: /data/app/~~TLEO_8XLgBa_y0O5XZ_ztA==/com.hxa.liquorDetection-10KwjrAku4e5aF7CKZiI9A==/base.apk
D PackageManager: updatedPkg = PackageSetting{dd36952 com.hxa.liquorDetection/10072}
I PackageManager: /data/app/~~TLEO_8XLgBa_y0O5XZ_ztA==/com.hxa.liquorDetection-10KwjrAku4e5aF7CKZiI9A== changed; collecting certs
W PackageManager: Relax SCAN_REQUIRE_KNOWN requirement for package com.hxa.liquorDetection
I PackageManager: Update system package com.hxa.liquorDetection code path from /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw== to /data/app/~~TLEO_8XLgBa_y0O5XZ_ztA==/com.hxa.liquorDetection-10KwjrAku4e5aF7CKZiI9A==; Retain data and using new
I PackageManager: Update system package com.hxa.liquorDetection resource path from /data/app/~~hS4pBWf_EmJVWTN5yccvXQ==/com.hxa.liquorDetection-o9M5-Vj2rJ5jU9C3I1VFYw== to /data/app/~~TLEO_8XLgBa_y0O5XZ_ztA==/com.hxa.liquorDetection-10KwjrAku4e5aF7CKZiI9A==; Retain data and using new
I PackageManager: Finished scanning non-system apps. Time: 172 ms, packageCount: 2 , timePerPackage: 86 , cached: 0
  • 源码:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
    // The version of the application on the /system partition is less than or
    // equal to the version on the /data partition. Throw an exception and use
    // the application already installed on the /data partition.
    throw new PackageManagerException(Log.WARN, "Package " + parsedPackage.getPackageName()
           + " at " + parsedPackage.getCodePath() + " ignored: updated version "
           + pkgSetting.versionCode + " better than this "
           + parsedPackage.getLongVersionCode());
}
...
if (throwable == null) {
    // TODO(toddke): move lower in the scan chain
    // Static shared libraries have synthetic package names
    if (parseResult.parsedPackage.isStaticSharedLibrary()) {
        renameStaticSharedLibraryPackage(parseResult.parsedPackage);
    }
    try {
        addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
                            currentTime, null);
    } catch (PackageManagerException e) {
        errorCode = e.error;
        Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
    }
} else if (throwable instanceof PackageParserException) {
    PackageParserException e = (PackageParserException)throwable;
    errorCode = e.error;
    Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage())
} else {
    throw new IllegalStateException("Unexpected exception occurred while parsing "
                        + parseResult.scanFile, throwable);
}

结合log和源码 看是解析/system/app/Huaxinan下的apk时,发现有新的版本85比6版本更好,然后抛出一个PackageManagerException异常,选择使用/data分区上的版本;
接着到扫描/data/app目录,log显示解析文件失败抛出一个PackageParserException的异常,错误码是INSTALL_PARSE_FAILED_NOT_APK,接着扫描/data/app下应用另一个版本目录。

看到此处的log有点怀疑是不是应用缓存没有清除或者哪里没有同步,在应用升级成功后/data/app下只看到当前版本的相关文件,并没有第二个此应用目录文件。

验证是否是缓存没有清除导致
①命令重启设备

adb install -r new.apk
adb reboot

设备重启后应用版本显示正常

②清除应用缓存

adb install -r new.apk
adb shell
pm clear com.hxa.liquorDetection

直接断电重启设备,应用版本显示正常。

最佳方式是使用同步,在应用安装成功后直接调用sync同步。

  • 源码:frameworks/base/services/core/java/com/android/server/pm/PackageInstallerSession.java
private static void sendOnPackageInstalled(Context context, IntentSender target, int sessionId,
        boolean showNotification, int userId, String basePackageName, int returnCode,
        String msg, Bundle extras) {
  	if (PackageManager.INSTALL_SUCCEEDED == returnCode && showNotification) {
        boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
        Notification notification = PackageInstallerService.buildSuccessNotification(context,
               context.getResources()
                     .getString(update ? R.string.package_updated_device_owner :
                                R.string.package_installed_device_owner),
                    basePackageName,
                    userId);
        if (notification != null) {
            NotificationManager notificationManager = (NotificationManager)
                    context.getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.notify(basePackageName,
                    SystemMessageProto.SystemMessage.NOTE_PACKAGE_STATE,
                    notification);
        }
    }
    // add start
    fileSync();
    // add end
    ...  
}

// add start
private static void fileSync(){
    Runtime runtime = Runtime.getRuntime();
    try {
        runtime.exec("sync");
    } catch (IOException e) {
        e.printStackTrace();
        android.util.Log.e(TAG, "fileSync"); 
    }
}
// add end

编译后刷机,升级应用直接断电重启设备,应用版本显示正常.

android 设备写入文件,立即断电重启后,文件丢失,数据没有保存问题
apk安装提示 Zip: EOCD not found, /storage/emulated/0/Download/*.apk is not zip

03-30 02:36