Merge "Fixing null check causing test breakage" into main
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index 3e9272d..70e01f5 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -240,7 +240,11 @@
icon.reset();
if (predictionCount > i) {
icon.setVisibility(View.VISIBLE);
- icon.applyFromWorkspaceItem(mPredictedApps.get(i));
+ WorkspaceItemInfo predictedItem = mPredictedApps.get(i);
+ predictedItem.rank = i;
+ predictedItem.cellX = i;
+ predictedItem.cellY = 0;
+ icon.applyFromWorkspaceItem(predictedItem);
} else {
icon.setVisibility(predictionCount == 0 ? GONE : INVISIBLE);
}
diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
index 87d5138..a3904bc 100644
--- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java
+++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
@@ -52,16 +52,38 @@
return Optional.empty();
}
- /** Get the Launcher overridden long press duration to trigger Assistant. */
+ /** Get the Launcher overridden long press nav handle duration to trigger Assistant. */
public Optional<Long> getLPNHDurationMillis() {
return Optional.empty();
}
- /** Get the Launcher overridden long press touch slop multiplier to trigger Assistant. */
+ /**
+ * Get the Launcher overridden long press nav handle touch slop multiplier to trigger Assistant.
+ */
public Optional<Float> getLPNHCustomSlopMultiplier() {
return Optional.empty();
}
+ /** Get the Launcher overridden long press home duration to trigger Assistant. */
+ public Optional<Long> getLPHDurationMillis() {
+ return Optional.empty();
+ }
+
+ /** Get the Launcher overridden long press home touch slop multiplier to trigger Assistant. */
+ public Optional<Float> getLPHCustomSlopMultiplier() {
+ return Optional.empty();
+ }
+
+ /** Get the long press duration data source. */
+ public int getDurationDataSource() {
+ return 0;
+ }
+
+ /** Get the long press touch slop multiplier data source. */
+ public int getSlopDataSource() {
+ return 0;
+ }
+
/** Return {@code true} if the Settings toggle is enabled. */
public boolean isSettingsAllEntrypointsEnabled() {
return false;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index adb9d2b..2e719cd 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1506,6 +1506,15 @@
}
@Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ boolean intercept = super.onInterceptTouchEvent(ev);
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ Log.d("b/318590728", "onInterceptTouchEvent: " + ev);
+ }
+ return intercept;
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
new file mode 100644
index 0000000..0c143b4
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+
+import com.android.launcher3.tapl.LauncherInstrumentation;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.Objects;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplPrivateSpaceTest extends AbstractQuickStepTest {
+
+ private int mProfileUserId;
+ private boolean mPrivateProfileSetupSuccessful;
+ private static final String TAG = "TaplPrivateSpaceTest";
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ initialize(this);
+
+ createAndStartPrivateProfileUser();
+ assumeTrue("Private Profile Setup not successful, aborting",
+ mPrivateProfileSetupSuccessful);
+
+ mDevice.pressHome();
+ waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
+ waitForStateTransitionToEnd("Launcher internal state didn't switch to Normal",
+ () -> NORMAL);
+ waitForResumed("Launcher internal state is still Background");
+ mLauncher.getWorkspace().switchToAllApps();
+ waitForStateTransitionToEnd("Launcher internal state didn't switch to All Apps",
+ () -> ALL_APPS);
+
+ // Wait for Private Space being available in Launcher.
+ waitForPrivateSpaceSetup();
+ // Wait for Launcher UI to be updated with Private Space Items.
+ waitForLauncherUIUpdate();
+ }
+
+ private void createAndStartPrivateProfileUser() {
+ String createUserOutput = executeShellCommand("pm create-user --profileOf 0 --user-type "
+ + "android.os.usertype.profile.PRIVATE LauncherPrivateProfile");
+ updatePrivateProfileSetupSuccessful("pm create-user", createUserOutput);
+ String[] tokens = createUserOutput.split("\\s+");
+ mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]);
+ StringBuilder logStr = new StringBuilder().append("profileId: ").append(mProfileUserId);
+ for (String str : tokens) {
+ logStr.append(str).append("\n");
+ }
+ String startUserOutput = executeShellCommand("am start-user " + mProfileUserId);
+ updatePrivateProfileSetupSuccessful("am start-user", startUserOutput);
+ }
+
+ @After
+ public void removePrivateProfile() {
+ String output = executeShellCommand("pm remove-user " + mProfileUserId);
+ updateProfileRemovalSuccessful("pm remove-user", output);
+ waitForPrivateSpaceRemoval();
+ }
+
+ @Test
+ public void testPrivateSpaceContainerIsPresent() {
+ assumeTrue(mPrivateProfileSetupSuccessful);
+ // Scroll to the bottom of All Apps
+ executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
+ waitForResumed("Launcher internal state is still Background");
+
+ // Verify Unlocked View elements are present.
+ assertNotNull("Private Space Unlocked View not found, or is not correct",
+ mLauncher.getAllApps().getPrivateSpaceUnlockedView());
+ }
+
+ private void waitForPrivateSpaceSetup() {
+ waitForLauncherCondition("Private Profile not setup",
+ launcher -> launcher.getAppsView().hasPrivateProfile(),
+ LauncherInstrumentation.WAIT_TIME_MS);
+ }
+
+ private void waitForPrivateSpaceRemoval() {
+ waitForLauncherCondition("Private Profile not setup",
+ launcher -> !launcher.getAppsView().hasPrivateProfile(),
+ LauncherInstrumentation.WAIT_TIME_MS);
+ }
+
+ private void waitForLauncherUIUpdate() {
+ // Wait for model thread completion as it may be processing
+ // the install event from the SystemService
+ mLauncher.waitForModelQueueCleared();
+ // Wait for Launcher UI thread completion, as it may be processing updating the UI in
+ // response to the model update. Not that `waitForLauncherInitialized` is just a proxy
+ // method, we can use any method which touches Launcher UI thread,
+ mLauncher.waitForLauncherInitialized();
+ }
+
+ private void updatePrivateProfileSetupSuccessful(String cli, String output) {
+ Log.d(TAG, "updatePrivateProfileSetupSuccessful, cli=" + cli + " " + "output="
+ + output);
+ mPrivateProfileSetupSuccessful = output.startsWith("Success");
+ }
+
+ private void updateProfileRemovalSuccessful(String cli, String output) {
+ Log.d(TAG, "updateProfileRemovalSuccessful, cli=" + cli + " " + "output=" + output);
+ assertTrue(output, output.startsWith("Success"));
+ }
+
+ private String executeShellCommand(String command) {
+ try {
+ return mDevice.executeShellCommand(command);
+ } catch (IOException e) {
+ Log.e(TAG, "error running shell command", e);
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3273f27..dbd594e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1551,7 +1551,13 @@
LauncherAppWidgetInfo launcherInfo,
CellPos presenterPos) {
CellLayout cellLayout = getCellLayout(launcherInfo.container, presenterPos.screenId);
- if (mStateManager.getState() == NORMAL) {
+ // We should wait until launcher is not animating to show resize frame so that
+ // {@link View#hasIdentityMatrix()} returns true (no scale effect) from CellLayout and
+ // Workspace (they are widget's parent view). Otherwise widget's
+ // {@link View#getLocationInWindow(int[])} will set skewed location, causing resize
+ // frame not showing at skewed location in
+ // {@link AppWidgetResizeFrame#snapToWidget(boolean)}.
+ if (mStateManager.getState() == NORMAL && !mStateManager.isInTransition()) {
AppWidgetResizeFrame.showForWidget(launcherHostView, cellLayout);
} else {
mStateManager.addStateListener(new StateManager.StateListener<LauncherState>() {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 60a6be6..50a597d 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -110,7 +110,7 @@
mOnTerminateCallback.add(() ->
mContext.getSystemService(LauncherApps.class).unregisterCallback(callbacks));
- if (Utilities.enableSupportForArchiving()) {
+ if (Flags.enableSupportForArchiving()) {
ArchiveCompatibilityParams params = new ArchiveCompatibilityParams();
params.setEnableUnarchivalConfirmation(false);
launcherApps.setArchiveCompatibility(params);
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index d44438f..2b886e4 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -830,10 +830,4 @@
// No-Op
}
}
-
- /** Encapsulates two flag checks into a single one. */
- public static boolean enableSupportForArchiving() {
- return Flags.enableSupportForArchiving()
- || getSystemProperty("pm.archiving.enabled", "false").equals("true");
- }
}
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 1633eba..af704a8 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -51,6 +51,7 @@
import androidx.annotation.VisibleForTesting;
import androidx.core.util.Pair;
+import com.android.launcher3.Flags;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
@@ -248,7 +249,7 @@
@SuppressWarnings("NewApi")
public synchronized void getTitleAndIcon(ItemInfoWithIcon info,
LauncherActivityInfo activityInfo, boolean useLowResIcon) {
- boolean isAppArchived = Utilities.enableSupportForArchiving() && activityInfo != null
+ boolean isAppArchived = Flags.enableSupportForArchiving() && activityInfo != null
&& activityInfo.getActivityInfo().isArchived;
// If we already have activity info, no need to use package icon
getTitleAndIcon(info, () -> activityInfo, isAppArchived, useLowResIcon,
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index 8659471..8c5ea79 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -33,6 +33,7 @@
import androidx.annotation.Nullable;
import com.android.launcher3.AppFilter;
+import com.android.launcher3.Flags;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.icons.IconCache;
@@ -330,7 +331,7 @@
PackageManagerHelper.getLoadingProgress(info),
PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
applicationInfo.intent = launchIntent;
- if (Utilities.enableSupportForArchiving()) {
+ if (Flags.enableSupportForArchiving()) {
// In case an app is archived, the respective item flag corresponding to
// archiving should also be applied during package updates
if (info.getActivityInfo().isArchived) {
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index d350879..90aba2a 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -40,6 +40,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import com.android.launcher3.Flags;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
@@ -300,7 +301,7 @@
} else {
lai = laiList.get(0);
si.intent = makeLaunchIntent(lai);
- if (Utilities.enableSupportForArchiving()
+ if (Flags.enableSupportForArchiving()
&& lai.getActivityInfo().isArchived) {
si.runtimeStatusFlags |= FLAG_ARCHIVED;
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index e0ced83..ac4c087 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -421,7 +421,7 @@
final HashMap<PackageUserKey, SessionInfo> installingPkgs =
mSessionHelper.getActiveSessions();
- if (Utilities.enableSupportForArchiving()) {
+ if (Flags.enableSupportForArchiving()) {
mInstallingPkgsCached = installingPkgs;
}
installingPkgs.forEach(mApp.getIconCache()::updateSessionCache);
@@ -695,7 +695,7 @@
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfo app = apps.get(i);
AppInfo appInfo = new AppInfo(app, mUserCache.getUserInfo(user), quietMode);
- if (Utilities.enableSupportForArchiving() && app.getApplicationInfo().isArchived) {
+ if (Flags.enableSupportForArchiving() && app.getApplicationInfo().isArchived) {
// For archived apps, include progress info in case there is a pending
// install session post restart of device.
String appPackageName = app.getApplicationInfo().packageName;
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index e42e679..1923065 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -276,7 +276,7 @@
PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
// In case an app is archived, we need to make sure that archived state
// in WorkspaceItemInfo is refreshed.
- if (Utilities.enableSupportForArchiving() && !activities.isEmpty()) {
+ if (Flags.enableSupportForArchiving() && !activities.isEmpty()) {
boolean newArchivalState = activities.get(
0).getActivityInfo().isArchived;
if (newArchivalState != si.isArchived()) {
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index ff95bbb..ee45c0f 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -26,6 +26,7 @@
import android.text.TextUtils
import android.util.Log
import android.util.LongSparseArray
+import com.android.launcher3.Flags
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherAppState
import com.android.launcher3.LauncherSettings.Favorites
@@ -335,7 +336,7 @@
}
if (
(c.restoreFlag != 0 ||
- Utilities.enableSupportForArchiving() &&
+ Flags.enableSupportForArchiving() &&
activityInfo != null &&
activityInfo.applicationInfo.isArchived) && !TextUtils.isEmpty(targetPkg)
) {
@@ -347,7 +348,7 @@
ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE.inv()
} else if (
activityInfo == null ||
- (Utilities.enableSupportForArchiving() &&
+ (Flags.enableSupportForArchiving() &&
activityInfo.applicationInfo.isArchived)
) {
// For archived apps, include progress info in case there is
@@ -479,7 +480,7 @@
!isSafeMode &&
(si == null) &&
(lapi == null) &&
- !(Utilities.enableSupportForArchiving() &&
+ !(Flags.enableSupportForArchiving() &&
pmHelper.isAppArchived(component.packageName))
) {
// Restore never started
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 210d720..93ba619 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -181,7 +181,7 @@
if (PackageManagerHelper.isAppSuspended(appInfo)) {
info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
}
- if (Utilities.enableSupportForArchiving() && lai.getActivityInfo().isArchived) {
+ if (Flags.enableSupportForArchiving() && lai.getActivityInfo().isArchived) {
info.runtimeStatusFlags |= FLAG_ARCHIVED;
}
info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index faeed29..3a74ff2 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -22,6 +22,7 @@
import androidx.annotation.Nullable;
+import com.android.launcher3.Flags;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags;
@@ -162,7 +163,7 @@
* Returns true if the app corresponding to the item is archived.
*/
public boolean isArchived() {
- if (!Utilities.enableSupportForArchiving()) {
+ if (!Flags.enableSupportForArchiving()) {
return false;
}
return (runtimeStatusFlags & FLAG_ARCHIVED) != 0;
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index f3769d5..4a3318e 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -29,6 +29,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import com.android.launcher3.Flags;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.Utilities;
@@ -217,7 +218,7 @@
&& !promiseIconAddedForId(sessionInfo.getSessionId())) {
// In case of unarchival, we do not want to add a workspace promise icon if one is
// not already present. For general app installations however, we do support it.
- if (!Utilities.enableSupportForArchiving() || !sessionInfo.isUnarchival()) {
+ if (!Flags.enableSupportForArchiving() || !sessionInfo.isUnarchival()) {
FileLog.d(LOG, "Adding package name to install queue: "
+ sessionInfo.getAppPackageName());
@@ -232,7 +233,7 @@
public boolean verifySessionInfo(@Nullable final PackageInstaller.SessionInfo sessionInfo) {
// For archived apps we always want to show promise icons and the checks below don't apply.
- if (Utilities.enableSupportForArchiving() && sessionInfo != null
+ if (Flags.enableSupportForArchiving() && sessionInfo != null
&& sessionInfo.isUnarchival()) {
return true;
}
diff --git a/src/com/android/launcher3/pm/InstallSessionTracker.java b/src/com/android/launcher3/pm/InstallSessionTracker.java
index eacbc11..24d58f3 100644
--- a/src/com/android/launcher3/pm/InstallSessionTracker.java
+++ b/src/com/android/launcher3/pm/InstallSessionTracker.java
@@ -31,6 +31,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import com.android.launcher3.Flags;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.PackageUserKey;
@@ -80,7 +81,7 @@
helper.tryQueuePromiseAppIcon(sessionInfo);
- if (Utilities.enableSupportForArchiving() && sessionInfo != null
+ if (Flags.enableSupportForArchiving() && sessionInfo != null
&& sessionInfo.isUnarchival()) {
// For archived apps, icon could already be present on the workspace. To make sure
// the icon state is updated, we send a change event.
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 49ec0cb..2a9ebbd 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -41,6 +41,7 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.BuildConfig;
+import com.android.launcher3.Flags;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings;
@@ -346,7 +347,7 @@
// Check for abandoned promise
if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()
- && (!Utilities.enableSupportForArchiving() || !shortcut.isArchived())) {
+ && (!Flags.enableSupportForArchiving() || !shortcut.isArchived())) {
String packageName = shortcut.getIntent().getComponent() != null
? shortcut.getIntent().getComponent().getPackageName()
: shortcut.getIntent().getPackage();
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 6ed875d..608bed7 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -40,6 +40,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.Flags;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -110,7 +111,7 @@
@SuppressWarnings("NewApi")
public boolean isAppArchivedForUser(@NonNull final String packageName,
@NonNull final UserHandle user) {
- if (!Utilities.enableSupportForArchiving()) {
+ if (!Flags.enableSupportForArchiving()) {
return false;
}
final ApplicationInfo info = getApplicationInfo(
@@ -273,6 +274,6 @@
@SuppressWarnings("NewApi")
private boolean isPackageInstalledOrArchived(ApplicationInfo info) {
return (info.flags & ApplicationInfo.FLAG_INSTALLED) != 0 || (
- Utilities.enableSupportForArchiving() && info.isArchived);
+ Flags.enableSupportForArchiving() && info.isArchived);
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 847dc4b..245ec09 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -416,6 +416,14 @@
}
}
+ /** Returns PrivateSpaceContainer if present in view. */
+ @NonNull
+ public PrivateSpaceContainer getPrivateSpaceUnlockedView() {
+ final UiObject2 allAppsContainer = verifyActiveContainer();
+ final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer);
+ return new PrivateSpaceContainer(mLauncher, appListRecycler);
+ }
+
protected abstract void verifyVisibleContainerOnDismiss();
/**
diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
new file mode 100644
index 0000000..2c16e01
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * View containing Private Space elements.
+ */
+public class PrivateSpaceContainer {
+ private static final String PS_HEADER_RES_ID = "ps_header_layout";
+ private static final String INSTALL_APP_TITLE = "Install apps";
+ private static final String DIVIDER_RES_ID = "private_space_divider";
+
+ private final LauncherInstrumentation mLauncher;
+ private final UiObject2 mAppListRecycler;
+
+ PrivateSpaceContainer(LauncherInstrumentation launcherInstrumentation,
+ UiObject2 appListRecycler) {
+ mLauncher = launcherInstrumentation;
+ mAppListRecycler = appListRecycler;
+
+ verifyHeaderIsPresent();
+ verifyInstallAppButtonIsPresent();
+ verifyDividerIsPresent();
+ }
+
+ // Assert PS Header is in view.
+ // Assert PS header has the correct elements.
+ private void verifyHeaderIsPresent() {
+ final UiObject2 psHeader = mLauncher.waitForObjectInContainer(mAppListRecycler,
+ PS_HEADER_RES_ID);
+ new PrivateSpaceHeader(mLauncher, psHeader, true);
+ }
+
+
+ // Assert Install App Item is present in view.
+ private void verifyInstallAppButtonIsPresent() {
+ mLauncher.getAllApps().getAppIcon(INSTALL_APP_TITLE);
+ }
+
+ // Assert Sys App Divider is present in view.
+ private void verifyDividerIsPresent() {
+ mLauncher.waitForObjectInContainer(mAppListRecycler, DIVIDER_RES_ID);
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java
new file mode 100644
index 0000000..3a7f038
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * View containing Private Space Header.
+ */
+public class PrivateSpaceHeader {
+ private static final String PS_HEADER_TEXT_RES_ID = "ps_container_header";
+ private static final String SETTINGS_BUTTON_RES_ID = "ps_settings_button";
+ private static final String UNLOCK_BUTTON_VIEW_RES_ID = "ps_lock_unlock_button";
+ private static final String LOCK_ICON_RES_ID = "lock_icon";
+ private static final String LOCK_TEXT_RES_ID = "lock_text";
+
+ private final UiObject2 mPrivateSpaceHeader;
+ private final boolean mPrivateSpaceEnabled;
+ private final LauncherInstrumentation mLauncher;
+
+ PrivateSpaceHeader(LauncherInstrumentation launcherInstrumentation,
+ UiObject2 privateSpaceHeader, boolean privateSpaceEnabled) {
+ mLauncher = launcherInstrumentation;
+ mPrivateSpaceHeader = privateSpaceHeader;
+ mPrivateSpaceEnabled = privateSpaceEnabled;
+ verifyPrivateSpaceHeaderState();
+ }
+
+ /** Verify elements in Private Space Header as per state */
+ private void verifyPrivateSpaceHeaderState() {
+ if (mPrivateSpaceEnabled) {
+ verifyUnlockedState();
+ } else {
+ mLauncher.fail("Private Space found in non enabled state");
+ }
+ }
+
+ /** Verify Unlocked State elements in Private Space Header */
+ private void verifyUnlockedState() {
+ UiObject2 headerText = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+ PS_HEADER_TEXT_RES_ID);
+ mLauncher.assertEquals("PS Header Text is incorrect ",
+ "Private", headerText.getText());
+
+ UiObject2 settingsButton = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+ SETTINGS_BUTTON_RES_ID);
+ mLauncher.waitForObjectEnabled(settingsButton, "Private Space Settings Button");
+ mLauncher.assertTrue("PS Settings button is non-clickable", settingsButton.isClickable());
+
+ UiObject2 unLockButtonView = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+ UNLOCK_BUTTON_VIEW_RES_ID);
+ mLauncher.waitForObjectEnabled(unLockButtonView, "Private Space Unlock Button");
+ mLauncher.assertTrue("PS Unlock Button is non-clickable", unLockButtonView.isClickable());
+
+ mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+ LOCK_ICON_RES_ID);
+
+ UiObject2 lockText = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+ LOCK_TEXT_RES_ID);
+ mLauncher.assertEquals("PS lock text is incorrect", "Lock", lockText.getText());
+
+ }
+}