Listen to LauncherUserInfo config changes and hide/unhide private space

entrypoint accordingly

Flag: android.multiuser.add_launcher_user_config

Bug: 346553745
Test: Manual - verified on device
Test: atest LauncherAppsTests

Change-Id: I202c4c76af4f96d5b3226daffcfebc2f9b9703b1
This commit is contained in:
Olivier Nshimiye
2024-09-10 19:20:42 +00:00
parent be17fb8a63
commit 39dee43e12
7 changed files with 80 additions and 24 deletions

View File

@@ -25,6 +25,7 @@ java_defaults {
name: "launcher-non-platform-apis-defaults",
static_libs: [
"android.os.flags-aconfig-java",
"android.multiuser.flags-aconfig-java",
"android.appwidget.flags-aconfig-java",
"com.android.window.flags.window-aconfig-java",
],

View File

@@ -27,6 +27,7 @@ import android.content.pm.ApplicationInfo
import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
import android.content.pm.ShortcutInfo
import android.multiuser.Flags.addLauncherUserConfig
import android.os.Bundle
import android.os.Flags.allowPrivateProfile
import android.os.IBinder
@@ -74,16 +75,14 @@ open class SystemApiWrapper @Inject constructor(@ApplicationContext context: Con
mContext.getSystemService(UserManager::class.java)!!.userProfiles?.forEach { user ->
mContext.getSystemService(LauncherApps::class.java)!!.getLauncherUserInfo(user)?.apply {
users[user] =
UserIconInfo(
user,
when (userType) {
UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK
UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED
UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE
else -> UserIconInfo.TYPE_MAIN
},
userSerialNumber.toLong(),
)
if (addLauncherUserConfig())
UserIconInfo(
user,
getUserIconType(userType),
userSerialNumber.toLong(),
userConfig,
)
else UserIconInfo(user, getUserIconType(userType), userSerialNumber.toLong())
}
}
return users
@@ -192,4 +191,13 @@ open class SystemApiWrapper @Inject constructor(@ApplicationContext context: Con
override fun getApplicationInfoHash(appInfo: ApplicationInfo): String =
(appInfo.sourceDir?.hashCode() ?: 0).toString() + " " + appInfo.longVersionCode
fun getUserIconType(userType: String): Int {
return when (userType) {
UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK
UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED
UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE
else -> UserIconInfo.TYPE_MAIN
}
}
}

View File

@@ -188,7 +188,9 @@ public class LauncherAppState implements SafeCloseable {
mOnTerminateCallback.add(() ->
settingsCache.unregister(NOTIFICATION_BADGING_URI, notificationLister));
// Register an observer to notify Launcher about Private Space settings toggle.
registerPrivateSpaceHideWhenLockListener(settingsCache);
if (!android.multiuser.Flags.addLauncherUserConfig()) {
registerPrivateSpaceHideWhenLockListener(settingsCache);
}
}
public LauncherAppState(Context context, @Nullable String iconCacheFileName) {

View File

@@ -16,6 +16,7 @@
package com.android.launcher3.allapps;
import static android.content.pm.LauncherUserInfo.PRIVATE_SPACE_ENTRYPOINT_HIDDEN;
import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
@@ -43,6 +44,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
@@ -78,11 +80,13 @@ import com.android.launcher3.pm.UserCache;
import com.android.launcher3.util.ApiWrapper;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.UserIconInfo;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.RecyclerViewFastScroller;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
/**
@@ -209,9 +213,20 @@ public class PrivateProfileManager extends UserProfileManager {
}
/** Whether private profile should be hidden on Launcher. */
@SuppressLint("NewApi")
public boolean isPrivateSpaceHidden() {
return getCurrentState() == STATE_DISABLED && SettingsCache.INSTANCE
.get(mAllApps.getContext()).getValue(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, 0);
UserHandle profileHandle = getProfileUser();
if (android.multiuser.Flags.addLauncherUserConfig() && !Objects.isNull(profileHandle)) {
UserIconInfo userInconInfo = UserCache.INSTANCE.get(mAllApps.getContext()).getUserInfo(
profileHandle);
return getCurrentState() == STATE_DISABLED && userInconInfo.getUserConfig().getBoolean(
PRIVATE_SPACE_ENTRYPOINT_HIDDEN, false);
}
return getCurrentState() == STATE_DISABLED && SettingsCache.INSTANCE.get(
mAllApps.getContext()).getValue(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, 0);
}
/**

View File

@@ -16,7 +16,9 @@
package com.android.launcher3.model
import android.annotation.SuppressLint
import android.content.pm.LauncherApps
import android.content.pm.LauncherUserInfo
import android.content.pm.PackageInstaller.SessionInfo
import android.content.pm.ShortcutInfo
import android.os.UserHandle
@@ -32,6 +34,7 @@ import com.android.launcher3.model.PackageUpdatedTask.OP_UNSUSPEND
import com.android.launcher3.model.PackageUpdatedTask.OP_UPDATE
import com.android.launcher3.pm.InstallSessionTracker
import com.android.launcher3.pm.PackageInstallInfo
import com.android.launcher3.pm.UserCache
import com.android.launcher3.util.PackageUserKey
import java.util.function.Consumer
@@ -134,6 +137,17 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask>
}
}
@SuppressLint("NewApi")
override fun onUserConfigChanged(launcherUserInfo: LauncherUserInfo) {
FileLog.d(TAG, "onUserConfigChanged for user ${launcherUserInfo.userType}")
if (android.multiuser.Flags.addLauncherUserConfig()) {
taskExecutor.accept { taskController, _, _ ->
UserCache.INSTANCE.get(taskController.app.context).updateCache()
taskController.app.model.forceReload()
}
}
}
companion object {
private const val TAG = "LauncherAppsCallbackImpl"
}

View File

@@ -26,7 +26,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
@@ -111,7 +110,7 @@ public class UserCache implements SafeCloseable {
updateCache();
}
@AnyThread
@WorkerThread
private void onUsersChanged(Intent intent) {
MODEL_EXECUTOR.execute(this::updateCache);
UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
@@ -123,7 +122,7 @@ public class UserCache implements SafeCloseable {
}
@WorkerThread
private void updateCache() {
public void updateCache() {
mUserToSerialMap = ApiWrapper.INSTANCE.get(mContext).queryAllUsers();
mUserToPreInstallAppMap = fetchPreInstallApps();
}

View File

@@ -16,8 +16,11 @@
package com.android.launcher3.util;
import static android.multiuser.Flags.addLauncherUserConfig;
import static com.android.launcher3.LauncherConstants.ActivityCodes.REQUEST_HOME_ROLE;
import android.annotation.SuppressLint;
import android.app.ActivityOptions;
import android.app.Person;
import android.app.role.RoleManager;
@@ -25,9 +28,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherUserInfo;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
@@ -45,6 +51,7 @@ import com.android.launcher3.dagger.LauncherAppSingleton;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.inject.Inject;
@@ -85,22 +92,32 @@ public class ApiWrapper {
/**
* Returns a map of all users on the device to their corresponding UI properties
*/
@SuppressLint("NewApi")
public Map<UserHandle, UserIconInfo> queryAllUsers() {
UserManager um = mContext.getSystemService(UserManager.class);
Map<UserHandle, UserIconInfo> users = new ArrayMap<>();
List<UserHandle> usersActual = um.getUserProfiles();
if (usersActual != null) {
for (UserHandle user : usersActual) {
long serial = um.getSerialNumberForUser(user);
// Simple check to check if the provided user is work profile
// TODO: Migrate to a better platform API
NoopDrawable d = new NoopDrawable();
boolean isWork = (d != mContext.getPackageManager().getUserBadgedIcon(d, user));
UserIconInfo info = new UserIconInfo(
user,
isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN,
serial);
UserIconInfo info;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
LauncherUserInfo userInfo = Objects.requireNonNull(
mContext.getSystemService(LauncherApps.class)).getLauncherUserInfo(
user);
long serial = Objects.requireNonNull(userInfo).getUserSerialNumber();
info = addLauncherUserConfig() ? new UserIconInfo(user,
isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN, serial,
userInfo.getUserConfig()) : new UserIconInfo(user,
isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN, serial);
} else {
long serial = um.getSerialNumberForUser(user);
// Simple check to check if the provided user is work profile
// TODO: Migrate to a better platform API
info = new UserIconInfo(user,
isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN, serial);
}
users.put(user, info);
}
}