summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Olivier Nshimiye <onshimiye@google.com> 2024-11-06 16:41:24 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-06 16:41:24 +0000
commit793c88f2313f2989dbfb03389f136b8f9a29d5a8 (patch)
tree955e2edaaadb9ab2c2eb534fcc46ba06a321ba99
parentce71447c9463561c561754909b38b81dcad55d30 (diff)
parentd34b2dab27690b5adf11a7eab8a056bfdb803a54 (diff)
Merge "Add support for LauncherUersInfo config" into main
-rw-r--r--core/api/current.txt3
-rw-r--r--core/java/android/content/pm/IOnAppsChangedListener.aidl2
-rw-r--r--core/java/android/content/pm/LauncherApps.java46
-rw-r--r--core/java/android/content/pm/LauncherUserInfo.java47
-rw-r--r--core/java/android/content/pm/multiuser.aconfig7
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java90
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java26
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;
}