diff options
author | 2024-11-06 16:41:24 +0000 | |
---|---|---|
committer | 2024-11-06 16:41:24 +0000 | |
commit | 793c88f2313f2989dbfb03389f136b8f9a29d5a8 (patch) | |
tree | 955e2edaaadb9ab2c2eb534fcc46ba06a321ba99 | |
parent | ce71447c9463561c561754909b38b81dcad55d30 (diff) | |
parent | d34b2dab27690b5adf11a7eab8a056bfdb803a54 (diff) |
Merge "Add support for LauncherUersInfo config" into main
-rw-r--r-- | core/api/current.txt | 3 | ||||
-rw-r--r-- | core/java/android/content/pm/IOnAppsChangedListener.aidl | 2 | ||||
-rw-r--r-- | core/java/android/content/pm/LauncherApps.java | 46 | ||||
-rw-r--r-- | core/java/android/content/pm/LauncherUserInfo.java | 47 | ||||
-rw-r--r-- | core/java/android/content/pm/multiuser.aconfig | 7 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/LauncherAppsService.java | 90 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 26 |
7 files changed, 213 insertions, 8 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index faecbf1990b5..7f74a62d5956 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -12735,6 +12735,7 @@ package android.content.pm { method public abstract void onPackagesUnavailable(String[], android.os.UserHandle, boolean); method public void onPackagesUnsuspended(String[], android.os.UserHandle); method public void onShortcutsChanged(@NonNull String, @NonNull java.util.List<android.content.pm.ShortcutInfo>, @NonNull android.os.UserHandle); + method @FlaggedApi("android.multiuser.add_launcher_user_config") public void onUserConfigChanged(@NonNull android.content.pm.LauncherUserInfo); } public static final class LauncherApps.PinItemRequest implements android.os.Parcelable { @@ -12770,10 +12771,12 @@ package android.content.pm { @FlaggedApi("android.os.allow_private_profile") public final class LauncherUserInfo implements android.os.Parcelable { method @FlaggedApi("android.os.allow_private_profile") public int describeContents(); + method @FlaggedApi("android.multiuser.add_launcher_user_config") @NonNull public android.os.Bundle getUserConfig(); method @FlaggedApi("android.os.allow_private_profile") public int getUserSerialNumber(); method @FlaggedApi("android.os.allow_private_profile") @NonNull public String getUserType(); method @FlaggedApi("android.os.allow_private_profile") public void writeToParcel(@NonNull android.os.Parcel, int); field @FlaggedApi("android.os.allow_private_profile") @NonNull public static final android.os.Parcelable.Creator<android.content.pm.LauncherUserInfo> CREATOR; + field @FlaggedApi("android.multiuser.add_launcher_user_config") public static final String PRIVATE_SPACE_ENTRYPOINT_HIDDEN = "private_space_entrypoint_hidden"; } public final class ModuleInfo implements android.os.Parcelable { diff --git a/core/java/android/content/pm/IOnAppsChangedListener.aidl b/core/java/android/content/pm/IOnAppsChangedListener.aidl index 830cbe0e0dd0..ade58c45b024 100644 --- a/core/java/android/content/pm/IOnAppsChangedListener.aidl +++ b/core/java/android/content/pm/IOnAppsChangedListener.aidl @@ -16,6 +16,7 @@ package android.content.pm; +import android.content.pm.LauncherUserInfo; import android.content.pm.ParceledListSlice; import android.os.Bundle; import android.os.UserHandle; @@ -34,4 +35,5 @@ oneway interface IOnAppsChangedListener { void onPackagesUnsuspended(in UserHandle user, in String[] packageNames); void onShortcutChanged(in UserHandle user, String packageName, in ParceledListSlice shortcuts); void onPackageLoadingProgressChanged(in UserHandle user, String packageName, float progress); + void onUserConfigChanged(in LauncherUserInfo launcherUserInfo); } diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 26f919f99ee9..26b835689b67 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -182,6 +182,8 @@ public class LauncherApps { */ public static final int FLAG_CACHE_PEOPLE_TILE_SHORTCUTS = 2; + private static final String LAUNCHER_USER_INFO_EXTRA_KEY = "launcher_user_info"; + /** @hide */ @IntDef(flag = false, prefix = { "FLAG_CACHE_" }, value = { FLAG_CACHE_NOTIFICATION_SHORTCUTS, @@ -349,6 +351,19 @@ public class LauncherApps { */ public void onPackageLoadingProgressChanged(@NonNull String packageName, @NonNull UserHandle user, float progress) {} + + /** + * Indicates {@link LauncherUserInfo} configs for a user have changed. The new + * {@link LauncherUserInfo} is given as a parameter. + * + * {@link LauncherUserInfo#getUserConfig} to get the updated user configs. + * + * @param launcherUserInfo The LauncherUserInfo of the user/profile whose configs have + * changed. + */ + @FlaggedApi(android.multiuser.Flags.FLAG_ADD_LAUNCHER_USER_CONFIG) + public void onUserConfigChanged(@NonNull LauncherUserInfo launcherUserInfo) { + } } /** @@ -2168,6 +2183,21 @@ public class LauncherApps { } } } + + public void onUserConfigChanged(LauncherUserInfo launcherUserInfo) { + if (DEBUG) { + if (Flags.allowPrivateProfile() + && android.multiuser.Flags.addLauncherUserConfig()) { + Log.d(TAG, "OnUserConfigChanged for user type " + launcherUserInfo.getUserType() + + ", new userConfig: " + launcherUserInfo.getUserConfig()); + } + } + synchronized (LauncherApps.this) { + for (CallbackMessageHandler callback : mCallbacks) { + callback.postOnUserConfigChanged(launcherUserInfo); + } + } + } }; /** @@ -2224,6 +2254,7 @@ public class LauncherApps { private static final int MSG_UNSUSPENDED = 7; private static final int MSG_SHORTCUT_CHANGED = 8; private static final int MSG_LOADING_PROGRESS_CHANGED = 9; + private static final int MSG_USER_CONFIG_CHANGED = 10; private final LauncherApps.Callback mCallback; @@ -2278,6 +2309,14 @@ public class LauncherApps { mCallback.onPackageLoadingProgressChanged(info.packageName, info.user, info.mLoadingProgress); break; + case MSG_USER_CONFIG_CHANGED: + if (Flags.allowPrivateProfile() + && android.multiuser.Flags.addLauncherUserConfig()) { + mCallback.onUserConfigChanged(Objects.requireNonNull( + info.launcherExtras.getParcelable(LAUNCHER_USER_INFO_EXTRA_KEY, + LauncherUserInfo.class))); + } + break; } } @@ -2353,6 +2392,13 @@ public class LauncherApps { info.mLoadingProgress = progress; obtainMessage(MSG_LOADING_PROGRESS_CHANGED, info).sendToTarget(); } + + public void postOnUserConfigChanged(LauncherUserInfo launcherUserInfo) { + CallbackInfo info = new CallbackInfo(); + info.launcherExtras = new Bundle(); + info.launcherExtras.putParcelable(LAUNCHER_USER_INFO_EXTRA_KEY, launcherUserInfo); + obtainMessage(MSG_USER_CONFIG_CHANGED, info).sendToTarget(); + } } /** diff --git a/core/java/android/content/pm/LauncherUserInfo.java b/core/java/android/content/pm/LauncherUserInfo.java index 8426f54d4754..574af5902e89 100644 --- a/core/java/android/content/pm/LauncherUserInfo.java +++ b/core/java/android/content/pm/LauncherUserInfo.java @@ -18,6 +18,7 @@ package android.content.pm; import android.annotation.FlaggedApi; import android.annotation.NonNull; +import android.os.Bundle; import android.os.Flags; import android.os.Parcel; import android.os.Parcelable; @@ -31,11 +32,25 @@ import android.os.UserManager; @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE) public final class LauncherUserInfo implements Parcelable { + /** + * A boolean extra indicating whether the private space entrypoint should be hidden when locked. + * + * @see #getUserConfig + */ + @FlaggedApi(android.multiuser.Flags.FLAG_ADD_LAUNCHER_USER_CONFIG) + public static final String PRIVATE_SPACE_ENTRYPOINT_HIDDEN = + "private_space_entrypoint_hidden"; + private final String mUserType; // Serial number for the user, should be same as in the {@link UserInfo} object. private final int mUserSerialNumber; + // Additional configs for the user, e.g., whether to hide the private space entrypoint when + // locked. + private final Bundle mUserConfig; + + /** * Returns type of the user as defined in {@link UserManager}. e.g., * {@link UserManager.USER_TYPE_PROFILE_MANAGED} or {@link UserManager.USER_TYPE_PROFILE_ClONE} @@ -50,6 +65,17 @@ public final class LauncherUserInfo implements Parcelable { } /** + * Returns additional configs for this launcher user + * + * @see #PRIVATE_SPACE_ENTRYPOINT_HIDDEN + */ + @FlaggedApi(android.multiuser.Flags.FLAG_ADD_LAUNCHER_USER_CONFIG) + @NonNull + public Bundle getUserConfig() { + return mUserConfig; + } + + /** * Returns serial number of user as returned by * {@link UserManager#getSerialNumberForUser(UserHandle)} * @@ -63,6 +89,7 @@ public final class LauncherUserInfo implements Parcelable { private LauncherUserInfo(@NonNull Parcel in) { mUserType = in.readString16NoHelper(); mUserSerialNumber = in.readInt(); + mUserConfig = in.readBundle(Bundle.class.getClassLoader()); } @Override @@ -70,6 +97,7 @@ public final class LauncherUserInfo implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString16NoHelper(mUserType); dest.writeInt(mUserSerialNumber); + dest.writeBundle(mUserConfig); } @Override @@ -99,23 +127,36 @@ public final class LauncherUserInfo implements Parcelable { private final String mUserType; private final int mUserSerialNumber; + private final Bundle mUserConfig; + + + @FlaggedApi(android.multiuser.Flags.FLAG_ADD_LAUNCHER_USER_CONFIG) + public Builder(@NonNull String userType, int userSerialNumber, @NonNull Bundle config) { + this.mUserType = userType; + this.mUserSerialNumber = userSerialNumber; + this.mUserConfig = config; + } public Builder(@NonNull String userType, int userSerialNumber) { this.mUserType = userType; this.mUserSerialNumber = userSerialNumber; + this.mUserConfig = new Bundle(); } /** * Builds the LauncherUserInfo object */ - @NonNull public LauncherUserInfo build() { - return new LauncherUserInfo(this.mUserType, this.mUserSerialNumber); + @NonNull + public LauncherUserInfo build() { + return new LauncherUserInfo(this.mUserType, this.mUserSerialNumber, this.mUserConfig); } } // End builder - private LauncherUserInfo(@NonNull String userType, int userSerialNumber) { + private LauncherUserInfo(@NonNull String userType, int userSerialNumber, + @NonNull Bundle config) { this.mUserType = userType; this.mUserSerialNumber = userSerialNumber; + this.mUserConfig = config; } } diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 528bde80cd3d..3d89ce12dec4 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -543,3 +543,10 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "add_launcher_user_config" + namespace: "profile_experiences" + description: "Add support for LauncherUserInfo configs" + bug: "346553745" +} diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 5653da07779b..2c0942337b1f 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -88,6 +88,7 @@ import android.content.pm.ShortcutServiceInternal; import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener; import android.content.pm.UserInfo; import android.content.pm.UserProperties; +import android.database.ContentObserver; import android.graphics.Rect; import android.multiuser.Flags; import android.net.Uri; @@ -95,6 +96,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IInterface; +import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteCallbackList; @@ -249,6 +251,7 @@ public class LauncherAppsService extends SystemService { private PackageInstallerService mPackageInstallerService; final LauncherAppsServiceInternal mInternal; + private SecureSettingsObserver mSecureSettingsObserver; @NonNull private final RemoteCallbackList<IDumpCallback> mDumpCallbacks = @@ -278,6 +281,7 @@ public class LauncherAppsService extends SystemService { mCallbackHandler = BackgroundThread.getHandler(); mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); mInternal = new LocalService(); + registerSettingsObserver(); } @VisibleForTesting @@ -2312,6 +2316,13 @@ public class LauncherAppsService extends SystemService { } } + void registerSettingsObserver() { + if (Flags.addLauncherUserConfig()) { + mSecureSettingsObserver = new SecureSettingsObserver(); + mSecureSettingsObserver.register(); + } + } + public static class ShortcutChangeHandler implements LauncherApps.ShortcutChangeCallback { private final UserManagerInternal mUserManagerInternal; @@ -2837,5 +2848,84 @@ public class LauncherAppsService extends SystemService { shortcutId, sourceBounds, startActivityOptions, targetUserId); } } + + class SecureSettingsObserver extends ContentObserver { + + SecureSettingsObserver() { + super(new Handler(Looper.getMainLooper())); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + if (uri.equals( + Settings.Secure.getUriFor(Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT))) { + + // This setting key only apply to private profile at the moment + UserHandle privateProfile = getPrivateProfile(); + if (privateProfile.getIdentifier() == UserHandle.USER_NULL) { + return; + } + + final int n = mListeners.beginBroadcast(); + try { + for (int i = 0; i < n; i++) { + final IOnAppsChangedListener listener = + mListeners.getBroadcastItem(i); + final BroadcastCookie cookie = + (BroadcastCookie) mListeners.getBroadcastCookie( + i); + if (!isEnabledProfileOf(cookie, privateProfile, + "onSecureSettingsChange")) { + Log.d(TAG, "onSecureSettingsChange: Skipping - profile not enabled" + + " or not accessible for package=" + cookie.packageName + + ", packageUid=" + cookie.callingUid); + } else { + try { + Log.d(TAG, + "onUserConfigChanged: triggering onUserConfigChanged"); + listener.onUserConfigChanged( + mUserManagerInternal.getLauncherUserInfo( + privateProfile.getIdentifier())); + } catch (RemoteException re) { + Slog.d(TAG, "onUserConfigChanged: Callback failed ", re); + } + } + } + } finally { + mListeners.finishBroadcast(); + } + } + } + + public void register() { + UserHandle privateProfile = getPrivateProfile(); + int parentUserId; + if (privateProfile.getIdentifier() == UserHandle.USER_NULL) { + // No private space available, register the observer for the current user + parentUserId = mContext.getUserId(); + } else { + parentUserId = mUserManagerInternal.getProfileParentId( + privateProfile.getIdentifier()); + } + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT), + true, this, parentUserId); + } + + public void unregister() { + mContext.getContentResolver().unregisterContentObserver(this); + } + + private UserHandle getPrivateProfile() { + UserInfo[] userInfos = mUserManagerInternal.getUserInfos(); + for (UserInfo u : userInfos) { + if (u.isPrivateProfile()) { + return UserHandle.of(u.id); + } + } + return UserHandle.of(UserHandle.USER_NULL); + } + } } } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 498659427a21..06e29c2c1408 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -21,6 +21,7 @@ import static android.content.Intent.ACTION_SCREEN_ON; import static android.content.Intent.EXTRA_USER_ID; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.content.pm.LauncherUserInfo.PRIVATE_SPACE_ENTRYPOINT_HIDDEN; import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE; import static android.content.pm.PackageManager.FEATURE_EMBEDDED; import static android.content.pm.PackageManager.FEATURE_LEANBACK; @@ -32,6 +33,7 @@ import static android.os.UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY; import static android.os.UserManager.USER_OPERATION_ERROR_UNKNOWN; import static android.os.UserManager.USER_OPERATION_ERROR_USER_RESTRICTED; import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE; +import static android.provider.Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT; import static com.android.internal.app.SetScreenLockDialogActivity.EXTRA_ORIGIN_USER_ID; import static com.android.internal.app.SetScreenLockDialogActivity.LAUNCH_REASON_DISABLE_QUIET_MODE; @@ -7946,11 +7948,25 @@ public class UserManagerService extends IUserManager.Stub { } if (userInfo != null) { final UserTypeDetails userDetails = getUserTypeDetails(userInfo); - final LauncherUserInfo uiInfo = new LauncherUserInfo.Builder( - userDetails.getName(), - userInfo.serialNumber) - .build(); - return uiInfo; + + if (Flags.addLauncherUserConfig()) { + Bundle config = new Bundle(); + if (userInfo.isPrivateProfile()) { + try { + int parentId = getProfileParentIdUnchecked(userId); + config.putBoolean(PRIVATE_SPACE_ENTRYPOINT_HIDDEN, + Settings.Secure.getIntForUser(mContext.getContentResolver(), + HIDE_PRIVATESPACE_ENTRY_POINT, parentId) == 1); + } catch (Settings.SettingNotFoundException e) { + throw new RuntimeException(e); + } + } + return new LauncherUserInfo.Builder(userDetails.getName(), + userInfo.serialNumber, config).build(); + } + + return new LauncherUserInfo.Builder(userDetails.getName(), + userInfo.serialNumber).build(); } else { return null; } |