Merge "Adding suport for Private Space QsTile fulfillment." into main
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index ad764e3..55438fe 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -260,7 +260,7 @@
mMainAdapterProvider = mSearchUiDelegate.createMainAdapterProvider();
if (Flags.enablePrivateSpace()) {
mPrivateSpaceHeaderViewController =
- new PrivateSpaceHeaderViewController(mPrivateProfileManager);
+ new PrivateSpaceHeaderViewController(this, mPrivateProfileManager);
}
mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN,
@@ -980,6 +980,11 @@
return mWorkManager;
}
+ /** Returns whether Private Profile has been setup. */
+ public boolean hasPrivateProfile() {
+ return mHasPrivateApps;
+ }
+
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
for (AdapterHolder holder : mAH) {
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 35c07c3..ad875e0 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -325,10 +325,6 @@
mPrivateProviderManager.addPrivateSpaceInstallAppButton(mAdapterItems);
position++;
addAppsWithSections(mPrivateApps, position);
- if (mActivityContext.getAppsView() != null) {
- mActivityContext.getAppsView().getActiveRecyclerView()
- .scrollToBottomWithMotion();
- }
break;
}
}
diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java
index c99b69f..aee511c 100644
--- a/src/com/android/launcher3/allapps/PrivateProfileManager.java
+++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_NOTHING;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SettingsCache.PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI;
@@ -34,7 +35,6 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BuildConfig;
-import com.android.launcher3.Flags;
import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.LauncherIcons;
@@ -59,11 +59,11 @@
private static final String SAFETY_CENTER_INTENT = Intent.ACTION_SAFETY_CENTER;
private static final String PS_SETTINGS_FRAGMENT_KEY = ":settings:fragment_args_key";
private static final String PS_SETTINGS_FRAGMENT_VALUE = "AndroidPrivateSpace_personal";
- private static final int ANIMATION_DURATION = 2000;
private final ActivityAllAppsContainerView<?> mAllApps;
private final Predicate<UserHandle> mPrivateProfileMatcher;
private PrivateAppsSectionDecorator mPrivateAppsSectionDecorator;
private boolean mPrivateSpaceSettingsAvailable;
+ private Runnable mUnlockRunnable;
public PrivateProfileManager(UserManager userManager,
ActivityAllAppsContainerView<?> allApps,
@@ -115,9 +115,17 @@
mAllApps.mAH.get(MAIN).mAdapter.notifyItemInserted(adapterItems.size() - 1);
}
- /** Disables quiet mode for Private Space User Profile. */
- public void unlockPrivateProfile() {
+ /**
+ * Disables quiet mode for Private Space User Profile.
+ * The runnable passed will be executed in the {@link #reset()} method,
+ * when Launcher receives update about profile availability.
+ * The runnable passed is only executed once, and reset after execution.
+ * In case the method is called again, before the previously set runnable was executed,
+ * the runnable will be updated.
+ */
+ public void unlockPrivateProfile(Runnable runnable) {
enableQuietMode(false);
+ mUnlockRunnable = runnable;
}
/** Enables quiet mode for Private Space User Profile. */
@@ -133,11 +141,15 @@
/** Resets the current state of Private Profile, w.r.t. to Launcher. */
public void reset() {
+ int previousState = getCurrentState();
boolean isEnabled = !mAllApps.getAppsStore()
.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED);
int updatedState = isEnabled ? STATE_ENABLED : STATE_DISABLED;
setCurrentState(updatedState);
resetPrivateSpaceDecorator(updatedState);
+ if (transitioningFromLockedToUnlocked(previousState, updatedState)) {
+ applyUnlockRunnable();
+ }
}
/** Opens the Private Space Settings Entry Point. */
@@ -182,13 +194,6 @@
}
// Add Private Space Decorator to the Recycler view.
mainAdapterHolder.mRecyclerView.addItemDecoration(mPrivateAppsSectionDecorator);
- if (Flags.privateSpaceAnimation() && mAllApps.getActiveRecyclerView()
- == mainAdapterHolder.mRecyclerView) {
- RecyclerViewAnimationController recyclerViewAnimationController =
- new RecyclerViewAnimationController(mAllApps);
- recyclerViewAnimationController.animateToState(true /* expand */,
- ANIMATION_DURATION, () -> {});
- }
} else {
// Remove Private Space Decorator from the Recycler view.
if (mPrivateAppsSectionDecorator != null) {
@@ -202,6 +207,18 @@
setQuietMode(enable);
}
+ void applyUnlockRunnable() {
+ if (mUnlockRunnable != null) {
+ // reset the runnable to prevent re-execution.
+ MAIN_EXECUTOR.post(mUnlockRunnable);
+ mUnlockRunnable = null;
+ }
+ }
+
+ private boolean transitioningFromLockedToUnlocked(int previousState, int updatedState) {
+ return previousState == STATE_DISABLED && updatedState == STATE_ENABLED;
+ }
+
@Override
public Predicate<UserHandle> getUserMatcher() {
return mPrivateProfileMatcher;
diff --git a/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java b/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
index 568ce32..bc3269d 100644
--- a/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
+++ b/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
@@ -16,6 +16,7 @@
package com.android.launcher3.allapps;
+import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
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;
@@ -28,6 +29,7 @@
import android.widget.ImageView;
import android.widget.RelativeLayout;
+import com.android.launcher3.Flags;
import com.android.launcher3.R;
import com.android.launcher3.allapps.UserProfileManager.UserProfileState;
@@ -36,9 +38,13 @@
* {@link UserProfileState}
*/
public class PrivateSpaceHeaderViewController {
+ private static final int ANIMATION_DURATION = 2000;
+ private final ActivityAllAppsContainerView mAllApps;
private final PrivateProfileManager mPrivateProfileManager;
- public PrivateSpaceHeaderViewController(PrivateProfileManager privateProfileManager) {
+ public PrivateSpaceHeaderViewController(ActivityAllAppsContainerView allApps,
+ PrivateProfileManager privateProfileManager) {
+ this.mAllApps = allApps;
this.mPrivateProfileManager = privateProfileManager;
}
@@ -77,7 +83,8 @@
quietModeButton.setOnClickListener(
view -> {
mPrivateProfileManager.logEvents(LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP);
- mPrivateProfileManager.unlockPrivateProfile();
+ mPrivateProfileManager.unlockPrivateProfile((this::
+ onPrivateProfileUnlocked));
});
}
default -> quietModeButton.setVisibility(View.GONE);
@@ -106,6 +113,21 @@
}
}
+ private void onPrivateProfileUnlocked() {
+ // If we are on main adapter view, we apply the PS Container expansion animation and
+ // then scroll down to load the entire container, making animation visible.
+ ActivityAllAppsContainerView<?>.AdapterHolder mainAdapterHolder =
+ (ActivityAllAppsContainerView<?>.AdapterHolder) mAllApps.mAH.get(MAIN);
+ if (Flags.enablePrivateSpace() && Flags.privateSpaceAnimation()
+ && mAllApps.getActiveRecyclerView() == mainAdapterHolder.mRecyclerView) {
+ RecyclerViewAnimationController recyclerViewAnimationController =
+ new RecyclerViewAnimationController(mAllApps);
+ recyclerViewAnimationController.animateToState(true /* expand */,
+ ANIMATION_DURATION, () -> {});
+ mAllApps.getActiveRecyclerView().scrollToBottomWithMotion();
+ }
+ }
+
PrivateProfileManager getPrivateProfileManager() {
return mPrivateProfileManager;
}
diff --git a/src/com/android/launcher3/allapps/UserProfileManager.java b/src/com/android/launcher3/allapps/UserProfileManager.java
index 6bef725..8894f45 100644
--- a/src/com/android/launcher3/allapps/UserProfileManager.java
+++ b/src/com/android/launcher3/allapps/UserProfileManager.java
@@ -22,7 +22,6 @@
import android.os.UserManager;
import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.StatsLogManager;
@@ -89,7 +88,6 @@
}
/** Returns current state for the profile type. */
- @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
public int getCurrentState() {
return mCurrentState;
}
diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
index 79d00c9..24f9acd 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.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing;
@@ -81,6 +82,8 @@
@Mock
private PackageManager mPackageManager;
+ private boolean mRunnableCalled = false;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -110,7 +113,7 @@
public void unlockPrivateProfile_requestsQuietModeAsFalse() throws Exception {
when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)).thenReturn(true);
- mPrivateProfileManager.unlockPrivateProfile();
+ mPrivateProfileManager.unlockPrivateProfile(() -> {});
awaitTasksCompleted();
Mockito.verify(mUserManager).requestQuietModeEnabled(false, PRIVATE_HANDLE);
@@ -133,6 +136,23 @@
}
@Test
+ public void transitioningToUnlocked_resetCallsPendingRunnable() throws Exception {
+ PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+ doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
+ when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
+ .thenReturn(false);
+ when(privateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED);
+ mRunnableCalled = false;
+
+ privateProfileManager.unlockPrivateProfile(this::testRunnable);
+ privateProfileManager.reset();
+
+ awaitTasksCompleted();
+ Mockito.verify(privateProfileManager).applyUnlockRunnable();
+ assertTrue(mRunnableCalled);
+ }
+
+ @Test
public void openPrivateSpaceSettings_triggersSecurityAndPrivacyIntent() {
Intent expectedIntent = new Intent(SAFETY_CENTER_INTENT);
expectedIntent.putExtra(PS_SETTINGS_FRAGMENT_KEY, PS_SETTINGS_FRAGMENT_VALUE);
@@ -150,4 +170,8 @@
private static void awaitTasksCompleted() throws Exception {
UI_HELPER_EXECUTOR.submit(() -> null).get();
}
+
+ private void testRunnable() {
+ mRunnableCalled = true;
+ }
}
diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java
index bc09cdd..92fff49 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java
@@ -64,13 +64,16 @@
private RelativeLayout mPsHeaderLayout;
@Mock
private PrivateProfileManager mPrivateProfileManager;
+ @Mock
+ private ActivityAllAppsContainerView mAllApps;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = new ActivityContextWrapper(getApplicationContext());
mLayoutInflater = LayoutInflater.from(getApplicationContext());
- mPsHeaderViewController = new PrivateSpaceHeaderViewController(mPrivateProfileManager);
+ mPsHeaderViewController = new PrivateSpaceHeaderViewController(mAllApps,
+ mPrivateProfileManager);
mPsHeaderLayout = (RelativeLayout) mLayoutInflater.inflate(R.layout.private_space_header,
null);
}