From a5ca62408381058c12bd5a1fe3b30f2512a73e03 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Wed, 1 Mar 2017 15:45:12 -0800 Subject: [PATCH] OMS: Introduce default overlays Default overlays are applied at first boot. They are specified by package name in system property ro.boot.vendor.overlay.theme as a semicolon separated list. Eg: ro.boot.vendor.overlay=com.android.vendor.overlay;com.android.vendor.overlay_two Test: manual (remove /data/system/overlays.xml and reboot) Change-Id: I8a7443a9059ccabfe1a63b075b95f1b2b6db7dbd --- core/java/android/app/LoadedApk.java | 2 +- .../InterestingConfigChanges.java | 3 +- .../server/om/OverlayManagerService.java | 30 ++++++++++- .../server/om/OverlayManagerServiceImpl.java | 26 +++++++--- .../server/om/OverlayManagerSettings.java | 1 - .../server/pm/PackageManagerService.java | 52 ++++++++----------- 6 files changed, 74 insertions(+), 40 deletions(-) diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 1c33e3865b01c..7cdd45fe8329e 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -286,7 +286,7 @@ public final class LoadedApk { final String apkName = path.substring(path.lastIndexOf(File.separator)); boolean match = false; for (String oldPath : oldPaths) { - final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator)); + final String oldApkName = oldPath.substring(oldPath.lastIndexOf(File.separator)); if (apkName.equals(oldApkName)) { match = true; break; diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java index d4623d6f46f65..82da9a38d7562 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java @@ -31,7 +31,8 @@ public class InterestingConfigChanges { public InterestingConfigChanges(int extraFlags) { mFlags = extraFlags | ActivityInfo.CONFIG_LOCALE - | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT; + | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT + | ActivityInfo.CONFIG_ASSETS_PATHS; } public boolean applyNewConfig(Resources res) { diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index ba4d46aa360be..a692559129adb 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -44,8 +44,11 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; +import android.os.SystemProperties; import android.os.UserHandle; +import android.text.TextUtils; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseArray; @@ -70,6 +73,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -193,6 +197,14 @@ public final class OverlayManagerService extends SystemService { static final String PERMISSION_DENIED = "Operation not permitted for user shell"; + /** + * The system property that specifies the default overlays to apply. + * This is a semicolon separated list of package names. + * + * Ex: com.android.vendor.overlay_one;com.android.vendor.overlay_two + */ + private static final String DEFAULT_OVERLAYS_PROP = "ro.boot.vendor.overlay.theme"; + private final Object mLock = new Object(); private final AtomicFile mSettingsFile; @@ -216,7 +228,8 @@ public final class OverlayManagerService extends SystemService { mUserManager = UserManagerService.getInstance(); IdmapManager im = new IdmapManager(installer); mSettings = new OverlayManagerSettings(); - mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings); + mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings, + getDefaultOverlayPackages()); final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(ACTION_PACKAGE_ADDED); @@ -257,6 +270,21 @@ public final class OverlayManagerService extends SystemService { updateAssets(newUserId, targets); } + private static Set getDefaultOverlayPackages() { + final String str = SystemProperties.get(DEFAULT_OVERLAYS_PROP); + if (TextUtils.isEmpty(str)) { + return Collections.emptySet(); + } + + final ArraySet defaultPackages = new ArraySet<>(); + for (String packageName : str.split(";")) { + if (!TextUtils.isEmpty(packageName)) { + defaultPackages.add(packageName); + } + } + return defaultPackages; + } + private final class PackageReceiver extends BroadcastReceiver { @Override public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 0e33409cd0ea1..ed493833139a5 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -27,8 +27,8 @@ import static com.android.server.om.OverlayManagerService.TAG; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.om.OverlayInfo; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; @@ -53,13 +53,16 @@ final class OverlayManagerServiceImpl { private final PackageManagerHelper mPackageManager; private final IdmapManager mIdmapManager; private final OverlayManagerSettings mSettings; + private final Set mDefaultOverlays; OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager, @NonNull final IdmapManager idmapManager, - @NonNull final OverlayManagerSettings settings) { + @NonNull final OverlayManagerSettings settings, + @NonNull final Set defaultOverlays) { mPackageManager = packageManager; mIdmapManager = idmapManager; mSettings = settings; + mDefaultOverlays = defaultOverlays; } /* @@ -92,12 +95,22 @@ final class OverlayManagerServiceImpl { final PackageInfo overlayPackage = overlayPackages.get(i); final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName); if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) { - if (oi != null) { - packagesToUpdateAssets.add(oi.targetPackageName); - } + // Update the overlay if it didn't exist or had the wrong target package. mSettings.init(overlayPackage.packageName, newUserId, overlayPackage.overlayTarget, overlayPackage.applicationInfo.getBaseCodePath()); + + if (oi == null) { + // This overlay does not exist in our settings. + if (mDefaultOverlays.contains(overlayPackage.packageName)) { + // Enable this overlay by default. + mSettings.setEnabled(overlayPackage.packageName, newUserId, true); + } + } else { + // The targetPackageName we have stored doesn't match the overlay's target. + // Queue the old target for an update as well. + packagesToUpdateAssets.add(oi.targetPackageName); + } } try { @@ -132,7 +145,7 @@ final class OverlayManagerServiceImpl { } } - return new ArrayList(packagesToUpdateAssets); + return new ArrayList<>(packagesToUpdateAssets); } void onUserRemoved(final int userId) { @@ -303,6 +316,7 @@ final class OverlayManagerServiceImpl { void onDump(@NonNull final PrintWriter pw) { mSettings.dump(pw); + pw.println("Default overlays: " + TextUtils.join(";", mDefaultOverlays)); } List getEnabledOverlayPackageNames(@NonNull final String targetPackageName, diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index 44908a748b32c..ff5c594c3ddea 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -45,7 +45,6 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; -import java.util.Map; /** * Data structure representing the current state of all overlay packages in the diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 838098310caf7..cbd3ebbb8c08b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -496,18 +496,6 @@ public class PackageManagerService extends IPackageManager.Stub { private static final String PACKAGE_SCHEME = "package"; private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay"; - /** - * If VENDOR_OVERLAY_THEME_PROPERTY is set, search for runtime resource overlay APKs also in - * VENDOR_OVERLAY_DIR/ in addition to - * VENDOR_OVERLAY_DIR. - */ - private static final String VENDOR_OVERLAY_THEME_PROPERTY = "ro.boot.vendor.overlay.theme"; - /** - * Same as VENDOR_OVERLAY_THEME_PROPERTY, except persistent. If set will override whatever - * is in VENDOR_OVERLAY_THEME_PROPERTY. - */ - private static final String VENDOR_OVERLAY_THEME_PERSIST_PROPERTY - = "persist.vendor.overlay.theme"; /** Permission grant: not grant the permission. */ private static final int GRANT_DENIED = 1; @@ -2470,16 +2458,6 @@ public class PackageManagerService extends IPackageManager.Stub { // Collect vendor overlay packages. (Do this before scanning any apps.) // For security and version matching reason, only consider // overlay packages if they reside in the right directory. - String overlayThemeDir = SystemProperties.get(VENDOR_OVERLAY_THEME_PERSIST_PROPERTY); - if (overlayThemeDir.isEmpty()) { - overlayThemeDir = SystemProperties.get(VENDOR_OVERLAY_THEME_PROPERTY); - } - if (!overlayThemeDir.isEmpty()) { - scanDirTracedLI(new File(VENDOR_OVERLAY_DIR, overlayThemeDir), mDefParseFlags - | PackageParser.PARSE_IS_SYSTEM - | PackageParser.PARSE_IS_SYSTEM_DIR - | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0); - } scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR @@ -3409,6 +3387,8 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } + rebaseEnabledOverlays(packageInfo.applicationInfo, userId); + packageInfo.packageName = packageInfo.applicationInfo.packageName = resolveExternalPackageNameLPr(p); @@ -4141,8 +4121,12 @@ public class PackageManagerService extends IPackageManager.Stub { if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; - return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId), - userId); + ActivityInfo ri = PackageParser.generateActivityInfo(a, flags, + ps.readUserState(userId), userId); + if (ri != null) { + rebaseEnabledOverlays(ri.applicationInfo, userId); + } + return ri; } } return null; @@ -4268,8 +4252,12 @@ public class PackageManagerService extends IPackageManager.Stub { if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; - return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId), - userId); + ServiceInfo si = PackageParser.generateServiceInfo(s, flags, + ps.readUserState(userId), userId); + if (si != null) { + rebaseEnabledOverlays(si.applicationInfo, userId); + } + return si; } } return null; @@ -4288,8 +4276,12 @@ public class PackageManagerService extends IPackageManager.Stub { if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; - return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId), - userId); + ProviderInfo pi = PackageParser.generateProviderInfo(p, flags, + ps.readUserState(userId), userId); + if (pi != null) { + rebaseEnabledOverlays(pi.applicationInfo, userId); + } + return pi; } } return null; @@ -23184,7 +23176,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); ArrayList paths = null; if (overlayPackageNames != null) { final int N = overlayPackageNames.size(); - paths = new ArrayList(N); + paths = new ArrayList<>(N); for (int i = 0; i < N; i++) { final String packageName = overlayPackageNames.get(i); final PackageParser.Package pkg = mPackages.get(packageName); @@ -23199,7 +23191,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); ArrayMap> userSpecificOverlays = mEnabledOverlayPaths.get(userId); if (userSpecificOverlays == null) { - userSpecificOverlays = new ArrayMap>(); + userSpecificOverlays = new ArrayMap<>(); mEnabledOverlayPaths.put(userId, userSpecificOverlays); }