@@ -1050,7 +1050,7 @@ public PackageManagerService(Context context, boolean factoryTest, boolean onlyC
10501050 mSystemInstallObserver .startWatching ();
10511051 scanDirLI (mSystemAppDir , PackageParser .PARSE_IS_SYSTEM
10521052 | PackageParser .PARSE_IS_SYSTEM_DIR , scanMode , 0 );
1053-
1053+
10541054 // Collect all vendor packages.
10551055 mVendorAppDir = new File ("/vendor/app" );
10561056 mVendorInstallObserver = new AppDirObserver (
@@ -1068,8 +1068,30 @@ public PackageManagerService(Context context, boolean factoryTest, boolean onlyC
10681068 Iterator <PackageSetting > psit = mSettings .mPackages .values ().iterator ();
10691069 while (psit .hasNext ()) {
10701070 PackageSetting ps = psit .next ();
1071- if ((ps .pkgFlags &ApplicationInfo .FLAG_SYSTEM ) == 0
1072- || mPackages .containsKey (ps .name )) {
1071+
1072+ /*
1073+ * If this is not a system app, it can't be a
1074+ * disable system app.
1075+ */
1076+ if ((ps .pkgFlags & ApplicationInfo .FLAG_SYSTEM ) == 0 ) {
1077+ continue ;
1078+ }
1079+
1080+ /*
1081+ * If the package is scanned, it's not erased.
1082+ */
1083+ if (mPackages .containsKey (ps .name )) {
1084+ /*
1085+ * If the system app is both scanned and in the
1086+ * disabled packages list, then it must have been
1087+ * added via OTA. Remove it from the currently
1088+ * scanned package so the previously user-installed
1089+ * application can be scanned.
1090+ */
1091+ if (mSettings .isDisabledSystemPackageLPr (ps .name )) {
1092+ mPackages .remove (ps .name );
1093+ }
1094+
10731095 continue ;
10741096 }
10751097
@@ -3096,22 +3118,71 @@ private PackageParser.Package scanPackageLI(File scanFile,
30963118 + "reverting from " + ps .codePathString
30973119 + ": new version " + pkg .mVersionCode
30983120 + " better than installed " + ps .versionCode );
3099- InstallArgs args = new FileInstallArgs ( ps .codePathString ,
3121+ InstallArgs args = createInstallArgs ( ps . pkgFlags , ps .codePathString ,
31003122 ps .resourcePathString , ps .nativeLibraryPathString );
3101- args .cleanUpResourcesLI ();
3102- mSettings .enableSystemPackageLPw (ps .name );
3123+ synchronized (mInstaller ) {
3124+ args .cleanUpResourcesLI ();
3125+ }
3126+ synchronized (mPackages ) {
3127+ mSettings .enableSystemPackageLPw (ps .name );
3128+ }
31033129 }
31043130 }
31053131 }
3132+
31063133 if (updatedPkg != null ) {
3107- // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
3134+ // An updated system app will not have the PARSE_IS_SYSTEM flag set
3135+ // initially
31083136 parseFlags |= PackageParser .PARSE_IS_SYSTEM ;
31093137 }
31103138 // Verify certificates against what was last scanned
31113139 if (!collectCertificatesLI (pp , ps , pkg , scanFile , parseFlags )) {
31123140 Slog .w (TAG , "Failed verifying certificates for package:" + pkg .packageName );
31133141 return null ;
31143142 }
3143+
3144+ /*
3145+ * A new system app appeared, but we already had a non-system one of the
3146+ * same name installed earlier.
3147+ */
3148+ boolean shouldHideSystemApp = false ;
3149+ if (updatedPkg == null && ps != null
3150+ && (parseFlags & PackageParser .PARSE_IS_SYSTEM_DIR ) != 0 && !isSystemApp (ps )) {
3151+ /*
3152+ * Check to make sure the signatures match first. If they don't,
3153+ * wipe the installed application and its data.
3154+ */
3155+ if (compareSignatures (ps .signatures .mSignatures , pkg .mSignatures )
3156+ != PackageManager .SIGNATURE_MATCH ) {
3157+ deletePackageLI (pkg .packageName , true , 0 , null , false );
3158+ ps = null ;
3159+ } else {
3160+ /*
3161+ * If the newly-added system app is an older version than the
3162+ * already installed version, hide it. It will be scanned later
3163+ * and re-added like an update.
3164+ */
3165+ if (pkg .mVersionCode < ps .versionCode ) {
3166+ shouldHideSystemApp = true ;
3167+ } else {
3168+ /*
3169+ * The newly found system app is a newer version that the
3170+ * one previously installed. Simply remove the
3171+ * already-installed application and replace it with our own
3172+ * while keeping the application data.
3173+ */
3174+ Slog .w (TAG , "Package " + ps .name + " at " + scanFile + "reverting from "
3175+ + ps .codePathString + ": new version " + pkg .mVersionCode
3176+ + " better than installed " + ps .versionCode );
3177+ InstallArgs args = createInstallArgs (ps .pkgFlags , ps .codePathString ,
3178+ ps .resourcePathString , ps .nativeLibraryPathString );
3179+ synchronized (mInstaller ) {
3180+ args .cleanUpResourcesLI ();
3181+ }
3182+ }
3183+ }
3184+ }
3185+
31153186 // The apk is forward locked (not public) if its code and resources
31163187 // are kept in different files.
31173188 // TODO grab this value from PackageSettings
@@ -3135,7 +3206,27 @@ private PackageParser.Package scanPackageLI(File scanFile,
31353206 // Set application objects path explicitly.
31363207 setApplicationInfoPaths (pkg , codePath , resPath );
31373208 // Note that we invoke the following method only if we are about to unpack an application
3138- return scanPackageLI (pkg , parseFlags , scanMode | SCAN_UPDATE_SIGNATURE , currentTime );
3209+ PackageParser .Package scannedPkg = scanPackageLI (pkg , parseFlags , scanMode
3210+ | SCAN_UPDATE_SIGNATURE , currentTime );
3211+
3212+ /*
3213+ * If the system app should be overridden by a previously installed
3214+ * data, hide the system app now and let the /data/app scan pick it up
3215+ * again.
3216+ */
3217+ if (shouldHideSystemApp ) {
3218+ synchronized (mPackages ) {
3219+ /*
3220+ * We have to grant systems permissions before we hide, because
3221+ * grantPermissions will assume the package update is trying to
3222+ * expand its permissions.
3223+ */
3224+ grantPermissionsLPw (pkg , true );
3225+ mSettings .disableSystemPackageLPw (pkg .packageName );
3226+ }
3227+ }
3228+
3229+ return scannedPkg ;
31393230 }
31403231
31413232 private static void setApplicationInfoPaths (PackageParser .Package pkg , String destCodePath ,
@@ -7177,6 +7268,10 @@ private static boolean isSystemApp(ApplicationInfo info) {
71777268 return (info .flags & ApplicationInfo .FLAG_SYSTEM ) != 0 ;
71787269 }
71797270
7271+ private static boolean isSystemApp (PackageSetting ps ) {
7272+ return (ps .pkgFlags & ApplicationInfo .FLAG_SYSTEM ) != 0 ;
7273+ }
7274+
71807275 private static boolean isUpdatedSystemApp (PackageParser .Package pkg ) {
71817276 return (pkg .applicationInfo .flags & ApplicationInfo .FLAG_UPDATED_SYSTEM_APP ) != 0 ;
71827277 }
0 commit comments