Merge "API to override the splashscreen theme" into sc-dev am: 8773bbe881
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13996772
Change-Id: I6130f6a5dcabfb37074f6fbb914a7a27bad1057a
diff --git a/core/api/current.txt b/core/api/current.txt
index 8fa4c3c..714074f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -56795,6 +56795,7 @@
public interface SplashScreen {
method public void clearOnExitAnimationListener();
method public void setOnExitAnimationListener(@NonNull android.window.SplashScreen.OnExitAnimationListener);
+ method public void setSplashScreenTheme(@StyleRes int);
}
public static interface SplashScreen.OnExitAnimationListener {
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 8cd622e..f8031be 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -799,6 +799,10 @@
void setMimeGroup(String packageName, String group, in List<String> mimeTypes);
+ String getSplashScreenTheme(String packageName, int userId);
+
+ void setSplashScreenTheme(String packageName, String themeName, int userId);
+
List<String> getMimeGroup(String packageName, String group);
boolean isAutoRevokeWhitelisted(String packageName);
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 55a6ab7..84317b3 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -81,6 +81,7 @@
public int installReason;
public @PackageManager.UninstallReason int uninstallReason;
public String harmfulAppWarning;
+ public String splashScreenTheme;
public ArraySet<String> disabledComponents;
public ArraySet<String> enabledComponents;
@@ -130,6 +131,7 @@
if (o.componentLabelIconOverrideMap != null) {
this.componentLabelIconOverrideMap = new ArrayMap<>(o.componentLabelIconOverrideMap);
}
+ splashScreenTheme = o.splashScreenTheme;
}
@Nullable
@@ -242,6 +244,7 @@
return componentLabelIconOverrideMap.get(componentName);
}
+
/**
* Test if this package is installed.
*/
@@ -479,7 +482,11 @@
}
if (harmfulAppWarning == null && oldState.harmfulAppWarning != null
|| (harmfulAppWarning != null
- && !harmfulAppWarning.equals(oldState.harmfulAppWarning))) {
+ && !harmfulAppWarning.equals(oldState.harmfulAppWarning))) {
+ return false;
+ }
+
+ if (!Objects.equals(splashScreenTheme, oldState.splashScreenTheme)) {
return false;
}
return true;
@@ -505,6 +512,7 @@
hashCode = 31 * hashCode + Objects.hashCode(disabledComponents);
hashCode = 31 * hashCode + Objects.hashCode(enabledComponents);
hashCode = 31 * hashCode + Objects.hashCode(harmfulAppWarning);
+ hashCode = 31 * hashCode + Objects.hashCode(splashScreenTheme);
return hashCode;
}
diff --git a/core/java/android/window/SplashScreen.java b/core/java/android/window/SplashScreen.java
index 18f29ae..7d222db 100644
--- a/core/java/android/window/SplashScreen.java
+++ b/core/java/android/window/SplashScreen.java
@@ -17,12 +17,17 @@
package android.window;
import android.annotation.NonNull;
+import android.annotation.StyleRes;
import android.annotation.SuppressLint;
import android.annotation.UiThread;
import android.app.Activity;
import android.app.ActivityThread;
+import android.app.AppGlobals;
import android.content.Context;
+import android.content.res.Resources;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
import android.util.Singleton;
import android.util.Slog;
@@ -60,6 +65,17 @@
*/
void clearOnExitAnimationListener();
+
+ /**
+ * Overrides the theme used for the {@link SplashScreen}s of this application.
+ * <p>
+ * By default, the {@link SplashScreen} uses the theme set in the manifest. This method
+ * overrides and persists the theme used for the {@link SplashScreen} of this application.
+ * <p>
+ * To reset to the default theme, set this the themeId to {@link Resources#ID_NULL}.
+ */
+ void setSplashScreenTheme(@StyleRes int themeId);
+
/**
* Listens for the splash screen exit event.
*/
@@ -84,6 +100,8 @@
* @hide
*/
class SplashScreenImpl implements SplashScreen {
+ private static final String TAG = "SplashScreenImpl";
+
private OnExitAnimationListener mExitAnimationListener;
private final IBinder mActivityToken;
private final SplashScreenManagerGlobal mGlobal;
@@ -119,6 +137,29 @@
mGlobal.removeImpl(this);
}
}
+
+ public void setSplashScreenTheme(@StyleRes int themeId) {
+ if (mActivityToken == null) {
+ Log.w(TAG, "Couldn't persist the starting theme. This instance is not an Activity");
+ return;
+ }
+
+ Activity activity = ActivityThread.currentActivityThread().getActivity(
+ mActivityToken);
+ if (activity == null) {
+ return;
+ }
+ String themeName = themeId != Resources.ID_NULL
+ ? activity.getResources().getResourceName(themeId) : null;
+
+ try {
+ AppGlobals.getPackageManager().setSplashScreenTheme(
+ activity.getComponentName().getPackageName(),
+ themeName, activity.getUserId());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Couldn't persist the starting theme", e);
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9464f00..19b7568 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -21629,7 +21629,8 @@
null /*disabledComponents*/,
PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.UNINSTALL_REASON_UNKNOWN,
- null /*harmfulAppWarning*/);
+ null /*harmfulAppWarning*/,
+ null /*splashScreenTheme*/);
}
mSettings.writeKernelMappingLPr(ps);
}
@@ -27742,6 +27743,23 @@
return mSettings.getPackageLPr(packageName).getMimeGroup(mimeGroup);
}
+ @Override
+ public void setSplashScreenTheme(@NonNull String packageName, @Nullable String themeId,
+ int userId) {
+ int callingUid = Binder.getCallingUid();
+ PackageSetting packageSetting = getPackageSettingForUser(packageName, callingUid, userId);
+ if (packageSetting != null) {
+ packageSetting.setSplashScreenTheme(userId, themeId);
+ }
+ }
+
+ @Override
+ public String getSplashScreenTheme(@NonNull String packageName, int userId) {
+ int callingUid = Binder.getCallingUid();
+ PackageSetting packageSetting = getPackageSettingForUser(packageName, callingUid, userId);
+ return packageSetting != null ? packageSetting.getSplashScreenTheme(userId) : null;
+ }
+
/**
* Temporary method that wraps mSettings.writeLPr() and calls mPermissionManager's
* writeLegacyPermissionsTEMP() beforehand.
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 7301ded..e2443c1 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -493,7 +493,8 @@
ArrayMap<String, PackageUserState.SuspendParams> suspendParams, boolean instantApp,
boolean virtualPreload, String lastDisableAppCaller,
ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
- int installReason, int uninstallReason, String harmfulAppWarning) {
+ int installReason, int uninstallReason, String harmfulAppWarning,
+ String splashScreenTheme) {
PackageUserState state = modifyUserState(userId);
state.ceDataInode = ceDataInode;
state.enabled = enabled;
@@ -512,6 +513,7 @@
state.instantApp = instantApp;
state.virtualPreload = virtualPreload;
state.harmfulAppWarning = harmfulAppWarning;
+ state.splashScreenTheme = splashScreenTheme;
onChanged();
}
@@ -522,7 +524,8 @@
otherState.instantApp,
otherState.virtualPreload, otherState.lastDisableAppCaller,
otherState.enabledComponents, otherState.disabledComponents,
- otherState.installReason, otherState.uninstallReason, otherState.harmfulAppWarning);
+ otherState.installReason, otherState.uninstallReason, otherState.harmfulAppWarning,
+ otherState.splashScreenTheme);
}
ArraySet<String> getEnabledComponents(int userId) {
@@ -723,6 +726,26 @@
}
/**
+ * @param userId the specified user to modify the theme for
+ * @param themeName the theme name to persist
+ * @see android.window.SplashScreen#setSplashScreenTheme(int)
+ */
+ public void setSplashScreenTheme(@UserIdInt int userId, @Nullable String themeName) {
+ modifyUserState(userId).splashScreenTheme = themeName;
+ }
+
+ /**
+ * @param userId the specified user to get the theme setting from
+ * @return the theme name previously persisted for the user or null
+ * if no splashscreen theme is persisted.
+ * @see android.window.SplashScreen#setSplashScreenTheme(int)
+ */
+ @Nullable
+ public String getSplashScreenTheme(@UserIdInt int userId) {
+ return readUserState(userId).splashScreenTheme;
+ }
+
+ /**
* @return True if package is still being loaded, false if the package is fully loaded.
*/
public boolean isPackageLoading() {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 0366014..0f947df 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -340,6 +340,7 @@
private static final String ATTR_INSTANT_APP = "instant-app";
private static final String ATTR_VIRTUAL_PRELOAD = "virtual-preload";
private static final String ATTR_HARMFUL_APP_WARNING = "harmful-app-warning";
+ private static final String ATTR_SPLASH_SCREEN_THEME = "splash-screen-theme";
private static final String ATTR_PACKAGE_NAME = "packageName";
private static final String ATTR_FINGERPRINT = "fingerprint";
@@ -939,7 +940,9 @@
null /*disabledComponents*/,
PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.UNINSTALL_REASON_UNKNOWN,
- null /*harmfulAppWarning*/);
+ null, /*harmfulAppWarning*/
+ null /*splashscreenTheme*/
+ );
}
}
}
@@ -1579,7 +1582,8 @@
null /*disabledComponents*/,
PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.UNINSTALL_REASON_UNKNOWN,
- null /*harmfulAppWarning*/);
+ null /*harmfulAppWarning*/,
+ null /* splashScreenTheme*/);
}
return;
}
@@ -1667,6 +1671,8 @@
PackageManager.INSTALL_REASON_UNKNOWN);
final int uninstallReason = parser.getAttributeInt(null, ATTR_UNINSTALL_REASON,
PackageManager.UNINSTALL_REASON_UNKNOWN);
+ final String splashScreenTheme = parser.getAttributeValue(null,
+ ATTR_SPLASH_SCREEN_THEME);
ArraySet<String> enabledComponents = null;
ArraySet<String> disabledComponents = null;
@@ -1739,7 +1745,8 @@
ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
hidden, distractionFlags, suspended, suspendParamsMap,
instantApp, virtualPreload, enabledCaller, enabledComponents,
- disabledComponents, installReason, uninstallReason, harmfulAppWarning);
+ disabledComponents, installReason, uninstallReason, harmfulAppWarning,
+ splashScreenTheme);
mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
} else if (tagName.equals("preferred-activities")) {
@@ -1996,6 +2003,10 @@
serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
ustate.harmfulAppWarning);
}
+ if (ustate.splashScreenTheme != null) {
+ serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
+ ustate.splashScreenTheme);
+ }
if (ustate.suspended) {
for (int i = 0; i < ustate.suspendParams.size(); i++) {
final String suspendingPackage = ustate.suspendParams.keyAt(i);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 721432e..d4707d6f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -176,12 +176,14 @@
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.ResumeActivityItem;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
@@ -6677,8 +6679,30 @@
prev = null;
}
}
- final int splashScreenThemeResId = options != null
+
+ // TODO(185200798): Persist theme name instead of theme if
+ int splashScreenThemeResId = options != null
? options.getSplashScreenThemeResId() : 0;
+
+ // User can override the splashscreen theme. The theme name is used to persist
+ // the setting, so if no theme is set in the ActivityOptions, we check if has
+ // been persisted here.
+ if (splashScreenThemeResId == 0) {
+ try {
+ String themeName = mAtmService.getPackageManager()
+ .getSplashScreenTheme(r.packageName, r.mUserId);
+ if (themeName != null) {
+ Context packageContext = mAtmService.mContext
+ .createPackageContext(r.packageName, 0);
+ splashScreenThemeResId = packageContext.getResources()
+ .getIdentifier(themeName, null, null);
+ }
+ } catch (RemoteException | PackageManager.NameNotFoundException
+ | Resources.NotFoundException ignore) {
+ // Just use the default theme
+ }
+ }
+
r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity),
splashScreenThemeResId, samePackage);
}