Merge "API to override the splashscreen theme" into sc-dev

This commit is contained in:
Vadim Caen
2021-04-26 19:20:04 +00:00
committed by Android (Google) Code Review
8 changed files with 138 additions and 8 deletions

View File

@@ -56795,6 +56795,7 @@ package android.window {
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 {

View File

@@ -796,6 +796,10 @@ interface IPackageManager {
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);

View File

@@ -81,6 +81,7 @@ public class PackageUserState {
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 @@ public class PackageUserState {
if (o.componentLabelIconOverrideMap != null) {
this.componentLabelIconOverrideMap = new ArrayMap<>(o.componentLabelIconOverrideMap);
}
splashScreenTheme = o.splashScreenTheme;
}
@Nullable
@@ -242,6 +244,7 @@ public class PackageUserState {
return componentLabelIconOverrideMap.get(componentName);
}
/**
* Test if this package is installed.
*/
@@ -479,7 +482,11 @@ public class PackageUserState {
}
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 @@ public class PackageUserState {
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;
}

View File

@@ -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 @@ public interface SplashScreen {
*/
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 @@ public interface SplashScreen {
* @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 @@ public interface SplashScreen {
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);
}
}
}
/**

View File

@@ -21627,7 +21627,8 @@ public class PackageManagerService extends IPackageManager.Stub
null /*disabledComponents*/,
PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.UNINSTALL_REASON_UNKNOWN,
null /*harmfulAppWarning*/);
null /*harmfulAppWarning*/,
null /*splashScreenTheme*/);
}
mSettings.writeKernelMappingLPr(ps);
}
@@ -27701,6 +27702,23 @@ public class PackageManagerService extends IPackageManager.Stub
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.

View File

@@ -493,7 +493,8 @@ public abstract class PackageSettingBase extends SettingBase {
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 @@ public abstract class PackageSettingBase extends SettingBase {
state.instantApp = instantApp;
state.virtualPreload = virtualPreload;
state.harmfulAppWarning = harmfulAppWarning;
state.splashScreenTheme = splashScreenTheme;
onChanged();
}
@@ -522,7 +524,8 @@ public abstract class PackageSettingBase extends SettingBase {
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) {
@@ -722,6 +725,26 @@ public abstract class PackageSettingBase extends SettingBase {
modifyUserState(userId).resetOverrideComponentLabelIcon();
}
/**
* @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.
*/

View File

@@ -340,6 +340,7 @@ public final class Settings implements Watchable, Snappable {
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 @@ public final class Settings implements Watchable, Snappable {
null /*disabledComponents*/,
PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.UNINSTALL_REASON_UNKNOWN,
null /*harmfulAppWarning*/);
null, /*harmfulAppWarning*/
null /*splashscreenTheme*/
);
}
}
}
@@ -1578,7 +1581,8 @@ public final class Settings implements Watchable, Snappable {
null /*disabledComponents*/,
PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.UNINSTALL_REASON_UNKNOWN,
null /*harmfulAppWarning*/);
null /*harmfulAppWarning*/,
null /* splashScreenTheme*/);
}
return;
}
@@ -1666,6 +1670,8 @@ public final class Settings implements Watchable, Snappable {
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;
@@ -1738,7 +1744,8 @@ public final class Settings implements Watchable, Snappable {
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")) {
@@ -1995,6 +2002,10 @@ public final class Settings implements Watchable, Snappable {
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);

View File

@@ -176,12 +176,14 @@ import android.app.servertransaction.NewIntentItem;
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 @@ class Task extends WindowContainer<WindowContainer> {
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);
}