Fixing Launcher crases due to methods being called on Ui Threads.
This CL fixes the following two issues:
1. Launcher crashing while calling `addPrivateSpaceSettingsButton` from
BaseAllAppsAdapter as the thread is UI
2. Decorator is not removed from Private Space Header during reset to
paused state. https://screenshot.googleplex.com/BZdLqaZQwdDApfV
Flag: ACONFIG com.android.launcher3.Flags.enable_private_space DEVELOPMENT
Bug: 311337961, 311342946
Test: Ran Launcher3 tests
Change-Id: I2763338ebf0f5468ad38f61a781e8a8334194c5c
diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java
index 3e73c6a..d8f6689 100644
--- a/src/com/android/launcher3/allapps/PrivateProfileManager.java
+++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SettingsCache.PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI;
import android.content.Intent;
@@ -27,6 +28,8 @@
import android.os.UserHandle;
import android.os.UserManager;
+import androidx.annotation.VisibleForTesting;
+
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.util.Preconditions;
@@ -47,6 +50,7 @@
private final ActivityAllAppsContainerView<?> mAllApps;
private final Predicate<UserHandle> mPrivateProfileMatcher;
private PrivateAppsSectionDecorator mPrivateAppsSectionDecorator;
+ private boolean mPrivateSpaceSettingsAvailable;
public PrivateProfileManager(UserManager userManager,
ActivityAllAppsContainerView<?> allApps,
@@ -55,6 +59,7 @@
super(userManager, statsLogManager, userCache);
mAllApps = allApps;
mPrivateProfileMatcher = (user) -> userCache.getUserInfo(user).isPrivate();
+ UI_HELPER_EXECUTOR.post(this::setPrivateSpaceSettingsAvailable);
}
/** Adds Private Space Header to the layout. */
@@ -87,6 +92,9 @@
boolean isEnabled = !mAllApps.getAppsStore()
.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED);
int updatedState = isEnabled ? STATE_ENABLED : STATE_DISABLED;
+ if (getCurrentState() == updatedState) {
+ return;
+ }
setCurrentState(updatedState);
resetPrivateSpaceDecorator(updatedState);
}
@@ -99,17 +107,24 @@
mAllApps.getContext().startActivity(psSettingsIntent);
}
- /**
- * Whether Private Space Settings Entry Point should be made visible. */
- public boolean isPrivateSpaceSettingsButtonVisible() {
+ /** Whether Private Space Settings Entry Point is available on the device. */
+ public boolean isPrivateSpaceSettingsAvailable() {
+ return mPrivateSpaceSettingsAvailable;
+ }
+
+ private void setPrivateSpaceSettingsAvailable() {
+ if (mPrivateSpaceSettingsAvailable) {
+ return;
+ }
Preconditions.assertNonUiThread();
Intent psSettingsIntent = new Intent(SAFETY_CENTER_INTENT);
psSettingsIntent.putExtra(PS_SETTINGS_FRAGMENT_KEY, PS_SETTINGS_FRAGMENT_VALUE);
- ResolveInfo resolveInfo = mAllApps.mActivityContext.getPackageManager()
+ ResolveInfo resolveInfo = mAllApps.getContext().getPackageManager()
.resolveActivity(psSettingsIntent, PackageManager.MATCH_SYSTEM_ONLY);
- return resolveInfo != null;
+ mPrivateSpaceSettingsAvailable = resolveInfo != null;
}
+ @VisibleForTesting
void resetPrivateSpaceDecorator(int updatedState) {
if (updatedState == STATE_ENABLED) {
// Add Private Space Decorator to the Recycler view.
diff --git a/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java b/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
index c49d0b1..79e0cce 100644
--- a/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
+++ b/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
@@ -19,7 +19,6 @@
import static com.android.launcher3.allapps.PrivateProfileManager.STATE_DISABLED;
import static com.android.launcher3.allapps.PrivateProfileManager.STATE_ENABLED;
import static com.android.launcher3.allapps.PrivateProfileManager.STATE_TRANSITION;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.view.View;
import android.widget.ImageButton;
@@ -50,7 +49,7 @@
//Add image and action for private space settings button
ImageButton settingsButton = parent.findViewById(R.id.ps_settings_button);
assert settingsButton != null;
- UI_HELPER_EXECUTOR.post(() -> addPrivateSpaceSettingsButton(settingsButton));
+ addPrivateSpaceSettingsButton(settingsButton);
//Add image for private space transitioning view
ImageView transitionView = parent.findViewById(R.id.ps_transition_image);
@@ -78,7 +77,7 @@
private void addPrivateSpaceSettingsButton(ImageButton settingsButton) {
if (mPrivateProfileManager.getCurrentState() == STATE_ENABLED
- && mPrivateProfileManager.isPrivateSpaceSettingsButtonVisible()) {
+ && mPrivateProfileManager.isPrivateSpaceSettingsAvailable()) {
settingsButton.setVisibility(View.VISIBLE);
settingsButton.setOnClickListener(view ->
mPrivateProfileManager.openPrivateSpaceSettings());
diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
index f461c8c..79d00c9 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
@@ -29,6 +30,8 @@
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
@@ -75,6 +78,8 @@
private Context mContext;
@Mock
private AllAppsStore mAllAppsStore;
+ @Mock
+ private PackageManager mPackageManager;
@Before
public void setUp() {
@@ -85,6 +90,8 @@
when(mUserCache.getUserInfo(PRIVATE_HANDLE)).thenReturn(PRIVATE_ICON_INFO);
when(mActivityAllAppsContainerView.getContext()).thenReturn(mContext);
when(mActivityAllAppsContainerView.getAppsStore()).thenReturn(mAllAppsStore);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.resolveActivity(any(), any())).thenReturn(new ResolveInfo());
mPrivateProfileManager = new PrivateProfileManager(mUserManager,
mActivityAllAppsContainerView, mStatsLogManager, mUserCache);
}
diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java
index ea8be3f..bc09cdd 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java
@@ -108,7 +108,7 @@
Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.bg_ps_lock_button));
Bitmap settingsImage = getBitmap(mContext.getDrawable(R.drawable.bg_ps_settings_button));
when(mPrivateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- when(mPrivateProfileManager.isPrivateSpaceSettingsButtonVisible()).thenReturn(true);
+ when(mPrivateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(true);
mPsHeaderViewController.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();
@@ -145,7 +145,7 @@
throws Exception {
Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.bg_ps_lock_button));
when(mPrivateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- when(mPrivateProfileManager.isPrivateSpaceSettingsButtonVisible()).thenReturn(false);
+ when(mPrivateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(false);
mPsHeaderViewController.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
awaitTasksCompleted();