Merge "Adding new tracing call from SysUI" into ub-launcher3-master
diff --git a/Android.bp b/Android.bp
index fc99880..cb695df 100644
--- a/Android.bp
+++ b/Android.bp
@@ -32,7 +32,7 @@
}
java_library_static {
- name: "launcher-log-protos-lite",
+ name: "launcher_log_protos_lite",
srcs: [
"protos/*.proto",
"proto_overrides/*.proto",
@@ -45,4 +45,5 @@
"proto_overrides",
],
},
+ static_libs: ["libprotobuf-java-lite"],
}
diff --git a/Android.mk b/Android.mk
index 66ccae0..c066a12 100644
--- a/Android.mk
+++ b/Android.mk
@@ -48,7 +48,9 @@
androidx.preference_preference \
iconloader_base
-LOCAL_STATIC_JAVA_LIBRARIES := LauncherPluginLib
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ LauncherPluginLib \
+ launcher_log_protos_lite
LOCAL_SRC_FILES := \
$(call all-proto-files-under, protos) \
@@ -144,7 +146,10 @@
LOCAL_AAPT2_ONLY := true
LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ SystemUISharedLib \
+ launcherprotosnano \
+ launcher_log_protos_lite
ifneq (,$(wildcard frameworks/base))
LOCAL_PRIVATE_PLATFORM_APIS := true
else
@@ -213,7 +218,10 @@
LOCAL_USE_AAPT2 := true
LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ SystemUISharedLib \
+ launcherprotosnano \
+ launcher_log_protos_lite
ifneq (,$(wildcard frameworks/base))
LOCAL_PRIVATE_PLATFORM_APIS := true
else
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 26698eb..d747bb8 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -44,6 +44,7 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<!--
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
index 7690b9d..3b3dc01 100644
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -16,6 +16,7 @@
package com.android.launcher3.model;
+import android.content.ComponentName;
import android.content.Context;
import android.os.UserHandle;
@@ -68,4 +69,9 @@
public void onPackageIconsUpdated(Set<String> packageNames, UserHandle user,
LauncherAppState app) {
}
+
+ public WidgetItem getWidgetProviderInfoByProviderName(
+ ComponentName providerName) {
+ return null;
+ }
}
\ No newline at end of file
diff --git a/proguard.flags b/proguard.flags
index 01302cf..e556c94 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -48,3 +48,6 @@
-dontwarn android.view.**
-dontwarn android.os.**
-dontwarn android.graphics.**
+
+# Ignore warnings for hidden utility classes referenced from the shared lib
+-dontwarn com.android.internal.util.**
\ No newline at end of file
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index 0560d68..ec1d55b 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -58,6 +58,35 @@
optional TipType tip_type = 17;
optional int32 search_query_length = 18;
optional bool is_work_app = 19;
+ optional FromFolderLabelState from_folder_label_state = 20;
+ optional ToFolderLabelState to_folder_label_state = 21;
+
+ // Note: proto does not support duplicate enum values, even if they belong to different enum type.
+ // Hence "FROM" and "TO" prefix added.
+ enum FromFolderLabelState{
+ FROM_FOLDER_LABEL_STATE_UNSPECIFIED = 0;
+ FROM_EMPTY = 1;
+ FROM_CUSTOM = 2;
+ FROM_SUGGESTED = 3;
+ }
+
+ enum ToFolderLabelState{
+ TO_FOLDER_LABEL_STATE_UNSPECIFIED = 0;
+ TO_SUGGESTION0_WITH_VALID_PRIMARY = 1;
+ TO_SUGGESTION1_WITH_VALID_PRIMARY = 2;
+ TO_SUGGESTION1_WITH_EMPTY_PRIMARY = 3;
+ TO_SUGGESTION2_WITH_VALID_PRIMARY = 4;
+ TO_SUGGESTION2_WITH_EMPTY_PRIMARY = 5;
+ TO_SUGGESTION3_WITH_VALID_PRIMARY = 6;
+ TO_SUGGESTION3_WITH_EMPTY_PRIMARY = 7;
+ TO_EMPTY_WITH_VALID_SUGGESTIONS = 8;
+ TO_EMPTY_WITH_EMPTY_SUGGESTIONS = 9;
+ TO_EMPTY_WITH_SUGGESTIONS_DISABLED = 10;
+ TO_CUSTOM_WITH_VALID_SUGGESTIONS = 11;
+ TO_CUSTOM_WITH_EMPTY_SUGGESTIONS = 12;
+ TO_CUSTOM_WITH_SUGGESTIONS_DISABLED = 13;
+ UNCHANGED = 14;
+ }
}
// Used to define what type of item a Target would represent.
@@ -120,6 +149,8 @@
BACK_GESTURE = 19;
UNDO = 20;
DISMISS_PREDICTION = 21;
+ HYBRID_HOTSEAT_ACCEPTED = 22;
+ HYBRID_HOTSEAT_CANCELED = 23;
}
enum TipType {
@@ -129,6 +160,7 @@
QUICK_SCRUB_TEXT = 3;
PREDICTION_TEXT = 4;
DWB_TOAST = 5;
+ HYBRID_HOTSEAT = 6;
}
// Used to define the action component of the LauncherEvent.
@@ -138,7 +170,8 @@
AUTOMATED = 1;
COMMAND = 2;
TIP = 3;
- // SOFT_KEYBOARD, HARD_KEYBOARD, ASSIST
+ SOFT_KEYBOARD = 4;
+ // HARD_KEYBOARD, ASSIST
}
enum Touch {
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 5d871c3..a06a2dd 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -24,6 +24,7 @@
<uses-permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS" />
<uses-permission android:name="android.permission.VIBRATE" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<application
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
@@ -46,10 +47,7 @@
</intent-filter>
</service>
- <!-- STOPSHIP: Change exported to false once all the integration is complete.
- It is set to true so that the activity can be started from command line -->
<activity android:name="com.android.quickstep.RecentsActivity"
- android:exported="true"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
@@ -92,12 +90,12 @@
android:directBootAware="true" />
<activity
- android:name="com.android.quickstep.interaction.BackGestureTutorialActivity"
+ android:name="com.android.quickstep.interaction.GestureSandboxActivity"
android:autoRemoveFromRecents="true"
android:excludeFromRecents="true"
android:screenOrientation="portrait">
<intent-filter>
- <action android:name="com.android.quickstep.action.BACK_GESTURE_TUTORIAL" />
+ <action android:name="com.android.quickstep.action.GESTURE_SANDBOX" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
diff --git a/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml b/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml
index fa3a0f8..4fda2a9 100644
--- a/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml
+++ b/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml
@@ -15,5 +15,5 @@
-->
<vector android:height="24dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@color/bottom_panel_background" android:pathData="M19 9l1.25-2.75L23 5l-2.75-1.25L19 1l-1.25 2.75L15 5l2.75 1.25L19 9zm-7.5.5L9 4 6.5 9.5 1 12l5.5 2.5L9 20l2.5-5.5L17 12l-5.5-2.5zM19 15l-1.25 2.75L15 19l2.75 1.25L19 23l1.25-2.75L23 19l-2.75-1.25L19 15z"/>
+ <path android:fillColor="?android:attr/colorAccent" android:pathData="M19 9l1.25-2.75L23 5l-2.75-1.25L19 1l-1.25 2.75L15 5l2.75 1.25L19 9zm-7.5.5L9 4 6.5 9.5 1 12l5.5 2.5L9 20l2.5-5.5L17 12l-5.5-2.5zM19 15l-1.25 2.75L15 19l2.75 1.25L19 23l1.25-2.75L23 19l-2.75-1.25L19 15z"/>
</vector>
diff --git a/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml b/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml
index d94c665..fe99037 100644
--- a/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml
+++ b/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml
@@ -24,13 +24,13 @@
<View
android:layout_width="match_parent"
android:layout_height="32dp"
- android:backgroundTint="@color/bottom_panel_background"
+ android:backgroundTint="?android:attr/colorAccent"
android:background="@drawable/bottom_sheet_top_border" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/bottom_panel_background"
+ android:background="?android:attr/colorAccent"
android:orientation="vertical">
<TextView
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
index f82af62..834e6cf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -296,7 +296,7 @@
predictedApp.container = LauncherSettings.Favorites.CONTAINER_PREDICTION;
predictedApps.add(predictedApp);
} else {
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
Log.e(TAG, "Predicted app not found: " + mapper);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index bfbd00e..e7290a4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -34,6 +34,7 @@
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.ActivityTracker;
+import com.android.launcher3.util.Themes;
import java.util.List;
@@ -109,7 +110,7 @@
NOTIFICATION_CHANNEL_ID)
.setContentTitle(name)
.setOngoing(true)
- .setColor(mLauncher.getColor(R.color.bottom_panel_background))
+ .setColor(Themes.getColorAccent(mLauncher))
.setContentIntent(PendingIntent.getActivity(mLauncher, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT))
.setSmallIcon(R.drawable.hotseat_edu_notification_icon)
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
index 4c87945..8926246 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
@@ -15,6 +15,9 @@
*/
package com.android.launcher3.hybridhotseat;
+import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.HYBRID_HOTSEAT_CANCELED;
+
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.res.Configuration;
@@ -32,6 +35,7 @@
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.uioverrides.PredictedAppIcon;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.views.AbstractSlideInView;
@@ -95,6 +99,7 @@
handleClose(true);
mHotseatEduController.migrate();
mHotseatEduController.finishOnboarding();
+ logUserAction(true);
Toast.makeText(mLauncher, R.string.hotseat_items_migrated, Toast.LENGTH_LONG).show();
}
@@ -102,6 +107,7 @@
if (mHotseatEduController == null) return;
Toast.makeText(getContext(), R.string.hotseat_no_migration, Toast.LENGTH_LONG).show();
mHotseatEduController.finishOnboarding();
+ logUserAction(false);
handleClose(true);
}
@@ -133,7 +139,28 @@
mLauncher.getDeviceProfile().hotseatBarSizePx + insets.bottom;
}
+ private void logUserAction(boolean migrated) {
+ LauncherLogProto.Action action = new LauncherLogProto.Action();
+ LauncherLogProto.Target target = new LauncherLogProto.Target();
+ action.type = LauncherLogProto.Action.Type.TOUCH;
+ action.touch = LauncherLogProto.Action.Touch.TAP;
+ target.containerType = LauncherLogProto.ContainerType.TIP;
+ target.tipType = LauncherLogProto.TipType.HYBRID_HOTSEAT;
+ target.controlType = migrated ? LauncherLogProto.ControlType.HYBRID_HOTSEAT_ACCEPTED
+ : HYBRID_HOTSEAT_CANCELED;
+ LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
+ UserEventDispatcher.newInstance(getContext()).dispatchUserEvent(event, null);
+ }
+ private void logOnBoardingSeen() {
+ LauncherLogProto.Action action = new LauncherLogProto.Action();
+ LauncherLogProto.Target target = new LauncherLogProto.Target();
+ action.type = LauncherLogProto.Action.Type.TIP;
+ target.containerType = LauncherLogProto.ContainerType.TIP;
+ target.tipType = LauncherLogProto.TipType.HYBRID_HOTSEAT;
+ LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
+ UserEventDispatcher.newInstance(getContext()).dispatchUserEvent(event, null);
+ }
private void animateOpen() {
if (mIsOpen || mOpenCloseAnimator.isRunning()) {
return;
@@ -164,7 +191,8 @@
|| predictions.size() < mLauncher.getDeviceProfile().inv.numHotseatIcons) {
return;
}
- mLauncher.getDragLayer().addView(this);
+ attachToContainer();
+ logOnBoardingSeen();
animateOpen();
for (int i = 0; i < mLauncher.getDeviceProfile().inv.numHotseatIcons; i++) {
WorkspaceItemInfo info = predictions.get(i);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index b2e1798..4bbb48c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -86,6 +86,7 @@
mIsDrawingDot = true;
int count = canvas.save();
canvas.translate(-getWidth() * RING_EFFECT_RATIO, -getHeight() * RING_EFFECT_RATIO);
+ canvas.scale(1 + 2 * RING_EFFECT_RATIO, 1 + 2 * RING_EFFECT_RATIO);
super.drawDotIfNecessary(canvas);
canvas.restoreToCount(count);
mIsDrawingDot = false;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index a1c8378..7895bac 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -37,6 +37,7 @@
import android.graphics.Rect;
import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
@@ -47,6 +48,7 @@
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
@@ -143,6 +145,10 @@
public void onStateTransitionEnd(Launcher launcher) {
launcher.getRotationHelper().setCurrentStateRequest(REQUEST_ROTATE);
DiscoveryBounce.showForOverviewIfNeeded(launcher);
+ RecentsView recentsView = launcher.getOverviewPanel();
+ AccessibilityManagerCompat.sendCustomAccessibilityEvent(
+ recentsView.getPageAt(recentsView.getCurrentPage()),
+ AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index b80830a..519939e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -172,7 +172,7 @@
mMotionPauseDetector.setDisallowPause(!handlingOverviewAnim()
|| upDisplacement < mMotionPauseMinDisplacement
|| upDisplacement > mMotionPauseMaxDisplacement);
- mMotionPauseDetector.addPosition(displacement, event.getEventTime());
+ mMotionPauseDetector.addPosition(event);
return super.onDrag(displacement, event);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 8628db0..799f1ad 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -317,7 +317,7 @@
// home screen elements will appear in the shelf on motion pause.
mMotionPauseDetector.setDisallowPause(mIsHomeScreenVisible
|| -displacement.y < mMotionPauseMinDisplacement);
- mMotionPauseDetector.addPosition(displacement.y, ev.getEventTime());
+ mMotionPauseDetector.addPosition(ev);
if (mIsHomeScreenVisible) {
// Cancel the shelf anim so it doesn't clobber mNonOverviewAnim.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index 28fc3da..1b6d291 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -234,6 +234,7 @@
public void adjustActivityControllerInterpolators() {
if (mAdjustInterpolatorsRunnable != null) {
mAdjustInterpolatorsRunnable.run();
+ mAdjustInterpolatorsRunnable = null;
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
index 482348f..345a147 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
@@ -917,6 +917,12 @@
windowAnim.addAnimatorListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
+ if (mRecentsAnimationController == null) {
+ // If the recents animation is interrupted, we still end the running
+ // animation (not canceled) so this is still called. In that case, we can
+ // skip doing any future work here for the current gesture.
+ return;
+ }
// Finalize the state and notify of the change
mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED);
}
@@ -938,6 +944,12 @@
windowAnim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
+ if (mRecentsAnimationController == null) {
+ // If the recents animation is interrupted, we still end the running
+ // animation (not canceled) so this is still called. In that case, we can
+ // skip doing any future work here for the current gesture.
+ return;
+ }
if (target == NEW_TASK && mRecentsView != null
&& mRecentsView.getNextPage() == mRecentsView.getRunningTaskIndex()) {
// We are about to launch the current running task, so use LAST_TASK state
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 70a2f9b..28e8fb6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -729,20 +729,15 @@
}
} else {
// Dump everything
+ FeatureFlags.dump(pw);
+ PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
mDeviceState.dump(pw);
+ mOverviewComponentObserver.dump(pw);
pw.println("TouchState:");
boolean resumed = mOverviewComponentObserver != null
&& mOverviewComponentObserver.getActivityInterface().isResumed();
pw.println(" resumed=" + resumed);
pw.println(" mConsumer=" + mConsumer.getName());
- pw.println("FeatureFlags:");
- pw.println(" APPLY_CONFIG_AT_RUNTIME=" + APPLY_CONFIG_AT_RUNTIME.get());
- pw.println(" QUICKSTEP_SPRINGS=" + QUICKSTEP_SPRINGS.get());
- pw.println(" UNSTABLE_SPRINGS=" + UNSTABLE_SPRINGS.get());
- pw.println(" ADAPTIVE_ICON_WINDOW_ANIM=" + ADAPTIVE_ICON_WINDOW_ANIM.get());
- pw.println(" ENABLE_QUICKSTEP_LIVE_TILE=" + ENABLE_QUICKSTEP_LIVE_TILE.get());
- pw.println(" ENABLE_HINTS_IN_OVERVIEW=" + ENABLE_HINTS_IN_OVERVIEW.get());
- pw.println(" FAKE_LANDSCAPE_UI=" + FAKE_LANDSCAPE_UI.get());
ActiveGestureLog.INSTANCE.dump("", pw);
pw.println("ProtoTrace:");
pw.println(" file="
@@ -777,7 +772,7 @@
protected boolean shouldNotifyBackGesture() {
return mBackGestureNotificationCounter > 0 &&
- mDeviceState.getGestureBlockedActivityPackage() != null;
+ !mDeviceState.getGestureBlockedActivityPackages().isEmpty();
}
@WorkerThread
@@ -786,8 +781,8 @@
mBackGestureNotificationCounter--;
Utilities.getDevicePrefs(this).edit()
.putInt(KEY_BACK_NOTIFICATION_COUNT, mBackGestureNotificationCounter).apply();
- sendBroadcast(new Intent(NOTIFY_ACTION_BACK).setPackage(
- mDeviceState.getGestureBlockedActivityPackage()));
+ mDeviceState.getGestureBlockedActivityPackages().forEach(blockedPackage ->
+ sendBroadcast(new Intent(NOTIFY_ACTION_BACK).setPackage(blockedPackage)));
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
index d3765c5..5ad48eb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
@@ -31,8 +31,8 @@
import com.android.launcher3.R;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.RecentsAnimationDeviceState;
-import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.MotionPauseDetector;
import com.android.systemui.shared.system.InputMonitorCompat;
/**
@@ -117,9 +117,7 @@
if (pointerIndex == -1) {
break;
}
-
- mMotionPauseDetector.addPosition(ev.getY(pointerIndex) - mDownY,
- ev.getEventTime());
+ mMotionPauseDetector.addPosition(ev, pointerIndex);
}
break;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 3ee3c2d..8e7074d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -59,6 +59,7 @@
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.CachedEventDispatcher;
import com.android.quickstep.util.MotionPauseDetector;
+import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -77,6 +78,7 @@
public static final float QUICKSTEP_TOUCH_SLOP_RATIO = 3;
private final RecentsAnimationDeviceState mDeviceState;
+ private final NavBarPosition mNavBarPosition;
private final TaskAnimationManager mTaskAnimationManager;
private final GestureState mGestureState;
private RecentsAnimationCallbacks mActiveCallbacks;
@@ -126,13 +128,16 @@
Factory handlerFactory) {
super(base);
mDeviceState = deviceState;
+ mNavBarPosition = mDeviceState.getNavBarPosition();
mTaskAnimationManager = taskAnimationManager;
mGestureState = gestureState;
mMainThreadHandler = new Handler(Looper.getMainLooper());
mHandlerFactory = handlerFactory;
mActivityInterface = mGestureState.getActivityInterface();
- mMotionPauseDetector = new MotionPauseDetector(base);
+ mMotionPauseDetector = new MotionPauseDetector(base, false,
+ mNavBarPosition.isLeftEdge() || mNavBarPosition.isRightEdge()
+ ? MotionEvent.AXIS_X : MotionEvent.AXIS_Y);
mMotionPauseMinDisplacement = base.getResources().getDimension(
R.dimen.motion_pause_detector_min_displacement_from_app);
mOnCompleteCallback = onCompleteCallback;
@@ -172,7 +177,7 @@
if (mPassedWindowMoveSlop && mInteractionHandler != null
&& !mRecentsViewDispatcher.hasConsumer()) {
mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
- mDeviceState.getNavBarPosition().getRotationMode()));
+ mNavBarPosition.getRotationMode()));
}
int edgeFlags = ev.getEdgeFlags();
ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
@@ -285,7 +290,7 @@
if (mDeviceState.isFullyGesturalNavMode()) {
mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
|| isLikelyToStartNewTask);
- mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
+ mMotionPauseDetector.addPosition(ev);
mInteractionHandler.setIsLikelyToStartNewTask(isLikelyToStartNewTask);
}
}
@@ -354,9 +359,9 @@
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
- float velocity = mDeviceState.getNavBarPosition().isRightEdge()
+ float velocity = mNavBarPosition.isRightEdge()
? velocityX
- : mDeviceState.getNavBarPosition().isLeftEdge()
+ : mNavBarPosition.isLeftEdge()
? -velocityX
: velocityY;
@@ -410,9 +415,9 @@
}
private float getDisplacement(MotionEvent ev) {
- if (mDeviceState.getNavBarPosition().isRightEdge()) {
+ if (mNavBarPosition.isRightEdge()) {
return ev.getX() - mDownPos.x;
- } else if (mDeviceState.getNavBarPosition().isLeftEdge()) {
+ } else if (mNavBarPosition.isLeftEdge()) {
return mDownPos.x - ev.getX();
} else {
return ev.getY() - mDownPos.y;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
index d5ed321..b9827ff 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
@@ -23,8 +23,8 @@
import com.android.launcher3.R;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
-import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.MotionPauseDetector;
/**
* An input consumer that detects swipe up and hold to exit screen pinning mode.
@@ -72,7 +72,7 @@
case MotionEvent.ACTION_MOVE:
float displacement = mTouchDownY - y;
mMotionPauseDetector.setDisallowPause(displacement < mMotionPauseMinDisplacement);
- mMotionPauseDetector.addPosition(y, ev.getEventTime());
+ mMotionPauseDetector.addPosition(ev);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 321af6c..fe78a84 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -92,6 +92,7 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.anim.SpringObjectAnimator;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -972,6 +973,10 @@
TaskView runningTask = getRunningTaskView();
if (runningTask != null) {
runningTask.setStableAlpha(isHidden ? 0 : mContentAlpha);
+ if (!isHidden) {
+ AccessibilityManagerCompat.sendCustomAccessibilityEvent(runningTask,
+ AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
+ }
}
}
@@ -1251,7 +1256,7 @@
}
public PendingAnimation createAllTasksDismissAnimation(long duration) {
- if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
+ if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
}
AnimatorSet anim = new AnimatorSet();
@@ -1595,7 +1600,7 @@
}
public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) {
- if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
+ if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index 49f667e..8ed1392 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -54,6 +54,7 @@
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.ConfigurationCompat;
/**
* A task in the Recents view.
@@ -357,7 +358,8 @@
final float thumbnailScale;
int thumbnailRotation = mThumbnailData.rotation;
- int currentRotation = getDisplay() != null ? getDisplay().getRotation() : 0;
+ int currentRotation = ConfigurationCompat.getWindowConfigurationRotation(
+ getResources().getConfiguration());
int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
// Landscape vs portrait change
boolean windowingModeSupportsRotation = !mActivity.isInMultiWindowMode()
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 327bb14..a688f9a 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -13,11 +13,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
- <string name="task_overlay_factory_class" translatable="false"></string>
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <string name="task_overlay_factory_class" translatable="false"/>
- <!-- Activity which blocks home gesture -->
- <string name="gesture_blocking_activity" translatable="false"></string>
+ <!-- Activities which block home gesture -->
+ <string-array name="gesture_blocking_activities" tools:ignore="InconsistentArrays">
+ <item>com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity</item>
+ </string-array>
<string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
@@ -32,5 +34,5 @@
<integer name="assistant_gesture_min_time_threshold">200</integer>
<integer name="assistant_gesture_corner_deg_threshold">20</integer>
- <string name="wellbeing_provider_pkg" translatable="false"></string>
+ <string name="wellbeing_provider_pkg" translatable="false"/>
</resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 5f81e1f..45a62ab 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -67,13 +67,13 @@
<string name="back_gesture_tutorial_close_button_content_description" translatable="false">Close</string>
<!-- Hotseat migration notification title -->
- <string translatable="false" name="hotseat_migrate_prompt_title">Get suggested apps on the home screen</string>
+ <string translatable="false" name="hotseat_migrate_prompt_title">Easily access your most-used apps</string>
<!-- Hotseat migration notification content -->
- <string translatable="false" name="hotseat_migrate_prompt_content">Tap to set up</string>
+ <string translatable="false" name="hotseat_migrate_prompt_content">Pixel suggests your favorite apps based on your routines. Tap to learn more.</string>
<!-- Hotseat migration wizard title -->
<string translatable="false" name="hotseat_migrate_title">Suggested apps replace the bottom row of apps</string>
<!-- Hotseat migration wizard message -->
- <string translatable="false" name="hotseat_migrate_message">To pin a favorite app, drag it over a suggested app. To hide a suggested app, touch & hold it.</string>
+ <string translatable="false" name="hotseat_migrate_message">Your current apps will move to the last screen. To pin or block a suggested app, drag it off the bottom row.</string>
<!-- Toast message user sees after opting into fully predicted hybrid hotseat -->
<string translatable="false" name="hotseat_items_migrated">Bottom row of apps moved to last screen</string>
<!-- Toast message user sees after opting into fully predicted hybrid hotseat -->
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 94ff63b..15503b8 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -167,7 +167,7 @@
@Override
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
if (requestCode != -1) {
- mPendingActivityRequestCode = -1;
+ mPendingActivityRequestCode = requestCode;
StartActivityParams params = new StartActivityParams(this, requestCode);
params.intent = intent;
params.options = options;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
index 6e7c087..2e422b7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
@@ -14,8 +14,12 @@
package com.android.launcher3.uioverrides.plugins;
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.plugins.Plugin;
@@ -24,6 +28,9 @@
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.plugins.PluginPrefs;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
public class PluginManagerWrapper {
@@ -75,4 +82,27 @@
public static boolean hasPlugins(Context context) {
return PluginPrefs.hasPlugins(context);
}
+
+ public void dump(PrintWriter pw) {
+ final List<ComponentName> enabledPlugins = new ArrayList<>();
+ final List<ComponentName> disabledPlugins = new ArrayList<>();
+ for (String action : getPluginActions()) {
+ for (ResolveInfo resolveInfo : mContext.getPackageManager().queryIntentServices(
+ new Intent(action), MATCH_DISABLED_COMPONENTS)) {
+ ComponentName installedPlugin = new ComponentName(
+ resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
+ if (mPluginEnabler.isEnabled(installedPlugin)) {
+ enabledPlugins.add(installedPlugin);
+ } else {
+ disabledPlugins.add(installedPlugin);
+ }
+ }
+ }
+
+ pw.println("PluginManager:");
+ pw.println(" numEnabledPlugins=" + enabledPlugins.size());
+ pw.println(" numDisabledPlugins=" + disabledPlugins.size());
+ pw.println(" enabledPlugins=" + enabledPlugins);
+ pw.println(" disabledPlugins=" + disabledPlugins);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index e88a8a4..b5e05ee 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -54,6 +54,12 @@
}
@Override
+ public void onStateDisabled(Launcher launcher) {
+ super.onStateDisabled(launcher);
+ AbstractFloatingView.closeAllOpenViews(launcher);
+ }
+
+ @Override
public String getDescription(Launcher launcher) {
AllAppsContainerView appsView = launcher.getAppsView();
return appsView.getDescription();
diff --git a/quickstep/src/com/android/quickstep/MultiStateCallback.java b/quickstep/src/com/android/quickstep/MultiStateCallback.java
index 6c65e01..b3875ae 100644
--- a/quickstep/src/com/android/quickstep/MultiStateCallback.java
+++ b/quickstep/src/com/android/quickstep/MultiStateCallback.java
@@ -130,7 +130,7 @@
final LinkedList<Runnable> callbacks;
if (mCallbacks.indexOfKey(stateMask) >= 0) {
callbacks = mCallbacks.get(stateMask);
- if (FeatureFlags.IS_DOGFOOD_BUILD && callbacks.contains(callback)) {
+ if (FeatureFlags.IS_STUDIO_BUILD && callbacks.contains(callback)) {
throw new IllegalStateException("Existing callback for state found");
}
} else {
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 73b78db..85ef4c6 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -35,6 +35,7 @@
import com.android.systemui.shared.system.PackageManagerWrapper;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;
@@ -233,4 +234,13 @@
public BaseActivityInterface getActivityInterface() {
return mActivityInterface;
}
+
+ public void dump(PrintWriter pw) {
+ pw.println("OverviewComponentObserver:");
+ pw.println(" isDefaultHome=" + mIsDefaultHome);
+ pw.println(" isHomeDisabled=" + mIsHomeDisabled);
+ pw.println(" homeAndOverviewSame=" + mIsHomeAndOverviewSame);
+ pw.println(" overviewIntent=" + mOverviewIntent);
+ pw.println(" homeIntent=" + mCurrentHomeIntent);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index acf61b4..0f98b32 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -62,6 +62,12 @@
mListeners.remove(listener);
}
+ @UiThread
+ public void removeAllListeners() {
+ Preconditions.assertUIThread();
+ mListeners.clear();
+ }
+
public void notifyAnimationCanceled() {
mCancelled = true;
onAnimationCanceled(null);
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 46af8bf..00adfbe 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -201,6 +201,7 @@
if (mInputConsumerController != null) {
mInputConsumerController.setInputListener(null);
}
+ mInputProxySupplier = null;
}
private boolean onInputConsumerEvent(InputEvent ev) {
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index d0afb21..abe1592 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -66,6 +66,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
/**
* Manages the state of the system during a swipe up gesture.
@@ -107,7 +109,7 @@
private Region mExclusionRegion;
private SystemGestureExclusionListenerCompat mExclusionListener;
- private ComponentName mGestureBlockedActivity;
+ private final List<ComponentName> mGestureBlockedActivities;
public RecentsAnimationDeviceState(Context context) {
final ContentResolver resolver = context.getContentResolver();
@@ -142,9 +144,19 @@
runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(this));
// Add any blocked activities
- String blockingActivity = context.getString(R.string.gesture_blocking_activity);
- if (!TextUtils.isEmpty(blockingActivity)) {
- mGestureBlockedActivity = ComponentName.unflattenFromString(blockingActivity);
+ String[] blockingActivities;
+ try {
+ blockingActivities =
+ context.getResources().getStringArray(R.array.gesture_blocking_activities);
+ } catch (Resources.NotFoundException e) {
+ blockingActivities = new String[0];
+ }
+ mGestureBlockedActivities = new ArrayList<>(blockingActivities.length);
+ for (String blockingActivity : blockingActivities) {
+ if (!TextUtils.isEmpty(blockingActivity)) {
+ mGestureBlockedActivities.add(
+ ComponentName.unflattenFromString(blockingActivity));
+ }
}
}
@@ -180,7 +192,7 @@
mDefaultDisplay.addChangeListener(this);
}
- if (mMode == NO_BUTTON) {
+ if (newMode == NO_BUTTON) {
mExclusionListener.register();
} else {
mExclusionListener.unregister();
@@ -272,17 +284,16 @@
* @return whether the given running task info matches the gesture-blocked activity.
*/
public boolean isGestureBlockedActivity(ActivityManager.RunningTaskInfo runningTaskInfo) {
- return runningTaskInfo != null && mGestureBlockedActivity != null
- && mGestureBlockedActivity.equals(runningTaskInfo.topActivity);
+ return runningTaskInfo != null
+ && mGestureBlockedActivities.contains(runningTaskInfo.topActivity);
}
/**
- * @return the package of the gesture-blocked activity or {@code null} if there is none.
+ * @return the packages of gesture-blocked activities.
*/
- public String getGestureBlockedActivityPackage() {
- return (mGestureBlockedActivity != null)
- ? mGestureBlockedActivity.getPackageName()
- : null;
+ public List<String> getGestureBlockedActivityPackages() {
+ return mGestureBlockedActivities.stream().map(ComponentName::getPackageName)
+ .collect(Collectors.toList());
}
/**
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index e3e8ace..6902e37 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -55,7 +55,7 @@
// Notify if recents animation is still running
if (mController != null) {
String msg = "New recents animation started before old animation completed";
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
throw new IllegalArgumentException(msg);
} else {
Log.e("TaskAnimationManager", msg, new Exception());
@@ -156,9 +156,9 @@
mTargets.release();
}
- // Remove gesture state from callbacks
- if (mCallbacks != null && mLastGestureState != null) {
- mCallbacks.removeListener(mLastGestureState);
+ // Clean up all listeners to ensure we don't get subsequent callbacks
+ if (mCallbacks != null) {
+ mCallbacks.removeAllListeners();
}
mController = null;
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
similarity index 76%
rename from quickstep/src/com/android/quickstep/interaction/BackGestureTutorialActivity.java
rename to quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 295ab48..8081ad7 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -16,7 +16,10 @@
package com.android.quickstep.interaction;
import android.graphics.Color;
+import android.graphics.Rect;
import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.Display;
import android.view.View;
import android.view.Window;
@@ -26,10 +29,11 @@
import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialStep;
import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialType;
+import java.util.List;
import java.util.Optional;
-/** Shows the Back gesture interactive tutorial in full screen mode. */
-public class BackGestureTutorialActivity extends FragmentActivity {
+/** Shows the gesture interactive sandbox in full screen mode. */
+public class GestureSandboxActivity extends FragmentActivity {
Optional<BackGestureTutorialFragment> mFragment = Optional.empty();
@@ -47,6 +51,12 @@
}
@Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ disableSystemGestures();
+ }
+
+ @Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
@@ -70,4 +80,14 @@
| View.SYSTEM_UI_FLAG_FULLSCREEN);
getWindow().setNavigationBarColor(Color.TRANSPARENT);
}
+
+ private void disableSystemGestures() {
+ Display display = getDisplay();
+ if (display != null) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ display.getMetrics(metrics);
+ getWindow().setSystemGestureExclusionRects(
+ List.of(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)));
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/BinderTracker.java b/quickstep/src/com/android/quickstep/util/BinderTracker.java
index 32d0d53..cb04e5b 100644
--- a/quickstep/src/com/android/quickstep/util/BinderTracker.java
+++ b/quickstep/src/com/android/quickstep/util/BinderTracker.java
@@ -31,7 +31,7 @@
private static final String TAG = "BinderTracker";
public static void start() {
- if (!FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (!FeatureFlags.IS_STUDIO_BUILD) {
Log.wtf(TAG, "Accessing tracker in released code.", new Exception());
return;
}
@@ -40,7 +40,7 @@
}
public static void stop() {
- if (!FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (!FeatureFlags.IS_STUDIO_BUILD) {
Log.wtf(TAG, "Accessing tracker in released code.", new Exception());
return;
}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index 9cf55b3..1d8a79f 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -84,6 +84,7 @@
float taskWidth, taskHeight, paddingHorz;
Resources res = context.getResources();
Rect insets = dp.getInsets();
+ final boolean overviewActionsEnabled = ENABLE_OVERVIEW_ACTIONS.get();
if (dp.isMultiWindowMode) {
if (multiWindowStrategy == MULTI_WINDOW_STRATEGY_HALF_SCREEN) {
@@ -113,7 +114,7 @@
final int paddingResId;
if (dp.isVerticalBarLayout()) {
paddingResId = R.dimen.landscape_task_card_horz_space;
- } else if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
+ } else if (overviewActionsEnabled && removeShelfFromOverview(context)) {
paddingResId = R.dimen.portrait_task_card_horz_space_big_overview;
} else {
paddingResId = R.dimen.portrait_task_card_horz_space;
@@ -121,9 +122,11 @@
paddingHorz = res.getDimension(paddingResId);
}
- float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
+ float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
float bottomMargin = thumbnailBottomMargin(context);
- float paddingVert = res.getDimension(R.dimen.task_card_vert_space);
+
+ float paddingVert = overviewActionsEnabled && removeShelfFromOverview(context)
+ ? 0 : res.getDimension(R.dimen.task_card_vert_space);
// Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
// we override the insets ourselves.
@@ -141,7 +144,7 @@
// Center in the visible space
float x = insets.left + (launcherVisibleWidth - outWidth) / 2;
float y = insets.top + Math.max(topIconMargin,
- (launcherVisibleHeight - extraVerticalSpace - outHeight) / 2);
+ (launcherVisibleHeight - extraVerticalSpace - outHeight - bottomMargin) / 2);
outRect.set(Math.round(x), Math.round(y),
Math.round(x) + Math.round(outWidth), Math.round(y) + Math.round(outHeight));
}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 801a560..d8b10b6 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -37,8 +37,7 @@
private static final long FORCE_PAUSE_TIMEOUT = 300;
/**
- * After {@link #makePauseHarderToTrigger()}, must
- * move slowly for this long to trigger a pause.
+ * After {@link #mMakePauseHarderToTrigger}, must move slowly for this long to trigger a pause.
*/
private static final long HARDER_TRIGGER_TIMEOUT = 400;
@@ -49,13 +48,10 @@
private final Alarm mForcePauseTimeout;
private final boolean mMakePauseHarderToTrigger;
private final Context mContext;
+ private final VelocityProvider mVelocityProvider;
- private Long mPreviousTime = null;
- private Float mPreviousPosition = null;
private Float mPreviousVelocity = null;
- private Float mFirstPosition = null;
-
private OnMotionPauseListener mOnMotionPauseListener;
private boolean mIsPaused;
// Bias more for the first pause to make it feel extra responsive.
@@ -73,6 +69,13 @@
* @param makePauseHarderToTrigger Used for gestures that require a more explicit pause.
*/
public MotionPauseDetector(Context context, boolean makePauseHarderToTrigger) {
+ this(context, makePauseHarderToTrigger, MotionEvent.AXIS_Y);
+ }
+
+ /**
+ * @param makePauseHarderToTrigger Used for gestures that require a more explicit pause.
+ */
+ public MotionPauseDetector(Context context, boolean makePauseHarderToTrigger, int axis) {
mContext = context;
Resources res = context.getResources();
mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
@@ -82,6 +85,7 @@
mForcePauseTimeout = new Alarm();
mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
mMakePauseHarderToTrigger = makePauseHarderToTrigger;
+ mVelocityProvider = new LinearVelocityProvider(axis);
}
/**
@@ -101,28 +105,28 @@
/**
* Computes velocity and acceleration to determine whether the motion is paused.
- * @param position The x or y component of the motion being tracked.
+ * @param ev The motion being tracked.
*
* TODO: Use historical positions as well, e.g. {@link MotionEvent#getHistoricalY(int, int)}.
*/
- public void addPosition(float position, long time) {
- if (mFirstPosition == null) {
- mFirstPosition = position;
- }
+ public void addPosition(MotionEvent ev) {
+ addPosition(ev, 0);
+ }
+
+ /**
+ * Computes velocity and acceleration to determine whether the motion is paused.
+ * @param ev The motion being tracked.
+ * @param pointerIndex Index for the pointer being tracked in the motion event
+ */
+ public void addPosition(MotionEvent ev, int pointerIndex) {
mForcePauseTimeout.setAlarm(mMakePauseHarderToTrigger
? HARDER_TRIGGER_TIMEOUT
: FORCE_PAUSE_TIMEOUT);
- if (mPreviousTime != null && mPreviousPosition != null) {
- long changeInTime = Math.max(1, time - mPreviousTime);
- float changeInPosition = position - mPreviousPosition;
- float velocity = changeInPosition / changeInTime;
- if (mPreviousVelocity != null) {
- checkMotionPaused(velocity, mPreviousVelocity, time);
- }
- mPreviousVelocity = velocity;
+ Float newVelocity = mVelocityProvider.addMotionEvent(ev, pointerIndex);
+ if (newVelocity != null && mPreviousVelocity != null) {
+ checkMotionPaused(newVelocity, mPreviousVelocity, ev.getEventTime());
}
- mPreviousTime = time;
- mPreviousPosition = position;
+ mPreviousVelocity = newVelocity;
}
private void checkMotionPaused(float velocity, float prevVelocity, long time) {
@@ -178,10 +182,8 @@
}
public void clear() {
- mPreviousTime = null;
- mPreviousPosition = null;
+ mVelocityProvider.clear();
mPreviousVelocity = null;
- mFirstPosition = null;
setOnMotionPauseListener(null);
mIsPaused = mHasEverBeenPaused = false;
mSlowStartTime = 0;
@@ -195,4 +197,55 @@
public interface OnMotionPauseListener {
void onMotionPauseChanged(boolean isPaused);
}
+
+ /**
+ * Interface to abstract out velocity calculations
+ */
+ protected interface VelocityProvider {
+
+ /**
+ * Adds a new motion events, and returns the velocity at this point, or null if
+ * the velocity is not available
+ */
+ Float addMotionEvent(MotionEvent ev, int pointer);
+
+ /**
+ * Clears all stored motion event records
+ */
+ void clear();
+ }
+
+ private static class LinearVelocityProvider implements VelocityProvider {
+
+ private Long mPreviousTime = null;
+ private Float mPreviousPosition = null;
+
+ private final int mAxis;
+
+ LinearVelocityProvider(int axis) {
+ mAxis = axis;
+ }
+
+ @Override
+ public Float addMotionEvent(MotionEvent ev, int pointer) {
+ long time = ev.getEventTime();
+ float position = ev.getAxisValue(mAxis, pointer);
+ Float velocity = null;
+
+ if (mPreviousTime != null && mPreviousPosition != null) {
+ long changeInTime = Math.max(1, time - mPreviousTime);
+ float changeInPosition = position - mPreviousPosition;
+ velocity = changeInPosition / changeInTime;
+ }
+ mPreviousTime = time;
+ mPreviousPosition = position;
+ return velocity;
+ }
+
+ @Override
+ public void clear() {
+ mPreviousTime = null;
+ mPreviousPosition = null;
+ }
+ }
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index d2f5d8f..724af66 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -25,7 +25,6 @@
import static org.junit.Assert.assertTrue;
import android.content.Intent;
-import android.os.RemoteException;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -48,7 +47,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -84,17 +82,6 @@
}
@Test
- @PortraitLandscape
- @Ignore // Enable after b/131115533
- public void testPressRecentAppsLauncherAndGetOverview() throws RemoteException {
- mDevice.pressRecentApps();
- waitForState("Launcher internal state didn't switch to Overview",
- () -> LauncherState.OVERVIEW);
-
- assertNotNull("getOverview() returned null", mLauncher.getOverview());
- }
-
- @Test
@NavigationModeSwitch
@PortraitLandscape
public void testWorkspaceSwitchToAllApps() {
@@ -271,10 +258,8 @@
@Test
@NavigationModeSwitch
@PortraitLandscape
- // b/143285809 Remove @Stability on 02/21/20 if the test doesn't flake.
+ // b/143285809 Remove @Stability on 02/27/20 if the test doesn't flake.
@TestStabilityRule.Stability(flavors = LOCAL | UNBUNDLED_POSTSUBMIT)
- // b/143285809
- @Ignore
public void testQuickSwitchFromApp() throws Exception {
startTestActivity(2);
startTestActivity(3);
diff --git a/res/layout/work_apps_paused.xml b/res/layout/work_apps_paused.xml
index 5607e78..1c18076 100644
--- a/res/layout/work_apps_paused.xml
+++ b/res/layout/work_apps_paused.xml
@@ -15,22 +15,22 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="?attr/allAppsScrimColor"
android:padding="8dp"
android:orientation="vertical"
- android:background="?attr/allAppsScrimColor"
android:gravity="center">
<ImageView
android:id="@+id/icon"
android:contentDescription="@string/work_apps_paused_title"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:tint="?attr/folderTextColor"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:tint="?attr/workProfileOverlayTextColor"
android:src="@drawable/ic_corp_off" />
<TextView
style="@style/TextHeadline"
- android:textColor="?attr/folderTextColor"
+ android:textColor="?attr/workProfileOverlayTextColor"
android:id="@+id/work_apps_paused_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -38,12 +38,12 @@
android:layout_marginBottom="8dp"
android:text="@string/work_apps_paused_title"
android:textAlignment="center"
- android:textSize="24sp" />
+ android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="?attr/folderTextColor"
+ android:textColor="?attr/workProfileOverlayTextColor"
android:text="@string/work_apps_paused_body"
android:textAlignment="center"
android:textSize="16sp" />
diff --git a/res/layout/work_profile_edu.xml b/res/layout/work_profile_edu.xml
index f7a529d..04094c4 100644
--- a/res/layout/work_profile_edu.xml
+++ b/res/layout/work_profile_edu.xml
@@ -21,22 +21,22 @@
<View
android:layout_width="match_parent"
- android:backgroundTint="@color/bottom_panel_background"
android:layout_height="32dp"
- android:background="@drawable/bottom_sheet_top_border" />
+ android:background="@drawable/bottom_sheet_top_border"
+ android:backgroundTint="?android:attr/colorAccent" />
<LinearLayout
android:id="@+id/view_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/bottom_panel_background"
+ android:background="?android:attr/colorAccent"
android:orientation="vertical"
android:paddingLeft="@dimen/bottom_sheet_edu_padding"
android:paddingRight="@dimen/bottom_sheet_edu_padding">
<TextView
- style="@style/TextHeadline"
android:id="@+id/content_text"
+ style="@style/TextHeadline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
@@ -57,5 +57,4 @@
android:textAlignment="center"
android:textColor="@android:color/white" />
</LinearLayout>
-
</com.android.launcher3.views.WorkEduView>
\ No newline at end of file
diff --git a/res/layout/work_tab_footer.xml b/res/layout/work_tab_footer.xml
index db95416..2cffedd 100644
--- a/res/layout/work_tab_footer.xml
+++ b/res/layout/work_tab_footer.xml
@@ -32,6 +32,8 @@
android:layout_weight="1"
android:drawableStart="@drawable/ic_corp"
android:drawablePadding="3dp"
+ android:drawableTint="?attr/workProfileOverlayTextColor"
+ android:textColor="?attr/workProfileOverlayTextColor"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center_vertical"
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index aef878b..5a15ec6 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -41,6 +41,7 @@
<attr name="folderIconBorderColor" format="color" />
<attr name="folderTextColor" format="color" />
<attr name="folderHintColor" format="color" />
+ <attr name="workProfileOverlayTextColor" format="color" />
<!-- BubbleTextView specific attributes. -->
<declare-styleable name="BubbleTextView">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 36f8468..194ef2c 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -45,5 +45,4 @@
<color name="back_gesture_tutorial_primary_color">#1A73E8</color> <!-- Blue -->
- <color name="bottom_panel_background">#f01A73E8</color>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bde3c31..9d0fb56 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -142,7 +142,7 @@
<string name="uninstall_system_app_text">This is a system app and can\'t be uninstalled.</string>
<!-- Default folder title -->
- <string name="folder_hint_text">Tap to edit</string>
+ <string name="folder_hint_text">Edit Name</string>
<!-- Accessibility -->
<!-- The format string for when an app is temporarily disabled. -->
@@ -330,7 +330,7 @@
<!--- User onboarding title for personal apps -->
<string name="work_profile_edu_personal_apps">Personal apps are private & can\'t be seen by IT</string>
<!--- User onboarding title for work profile apps -->
- <string name="work_profile_edu_work_apps">Work apps are badged and monitored by IT</string>
+ <string name="work_profile_edu_work_apps">Work apps are badged & visible to IT</string>
<!-- Action label to proceed to the next work profile edu section-->
<string name="work_profile_edu_next">Next</string>
<!-- Action label to finish work profile edu-->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 1174a2f..cee268b 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -50,6 +50,7 @@
<item name="folderTextColor">#FF212121</item>
<item name="folderHintColor">#FF616161</item>
<item name="loadingIconColor">#CCFFFFFF</item>
+ <item name="workProfileOverlayTextColor">#FF212121</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
@@ -77,6 +78,7 @@
<item name="folderFillColor">#CDFFFFFF</item>
<item name="folderIconBorderColor">#FF80868B</item>
<item name="folderTextColor">?attr/workspaceTextColor</item>
+
</style>
<style name="LauncherTheme.Dark" parent="@style/LauncherTheme">
@@ -100,6 +102,7 @@
<item name="folderHintColor">#FFCCCCCC</item>
<item name="isMainColorDark">true</item>
<item name="loadingIconColor">#99FFFFFF</item>
+ <item name="workProfileOverlayTextColor">@android:color/white</item>
</style>
<style name="LauncherTheme.Dark.DarkMainColor" parent="@style/LauncherTheme.Dark">
diff --git a/robolectric_tests/src/com/android/launcher3/folder/FolderNameProviderTest.java b/robolectric_tests/src/com/android/launcher3/folder/FolderNameProviderTest.java
index f769055..74ef55e 100644
--- a/robolectric_tests/src/com/android/launcher3/folder/FolderNameProviderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/folder/FolderNameProviderTest.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.folder;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
import android.content.ComponentName;
import android.content.Context;
@@ -61,15 +61,16 @@
ArrayList<WorkspaceItemInfo> list = new ArrayList<>();
list.add(mItem1);
list.add(mItem2);
- String[] suggestedNameOut = new String[FolderNameProvider.SUGGEST_MAX];
- new FolderNameProvider().getSuggestedFolderName(mContext, list, suggestedNameOut);
- assertTrue(suggestedNameOut[0].equals("Work"));
+ FolderNameInfo[] nameInfos =
+ new FolderNameInfo[FolderNameProvider.SUGGEST_MAX];
+ new FolderNameProvider().getSuggestedFolderName(mContext, list, nameInfos);
+ assertEquals("Work", nameInfos[0].getLabel());
- suggestedNameOut[0] = "candidate1";
- suggestedNameOut[1] = "candidate2";
- suggestedNameOut[2] = "candidate3";
- new FolderNameProvider().getSuggestedFolderName(mContext, list, suggestedNameOut);
- assertTrue(suggestedNameOut[3].equals("Work"));
+ nameInfos[0] = new FolderNameInfo("candidate1", 0.9);
+ nameInfos[1] = new FolderNameInfo("candidate2", 0.8);
+ nameInfos[2] = new FolderNameInfo("candidate3", 0.7);
+ new FolderNameProvider().getSuggestedFolderName(mContext, list, nameInfos);
+ assertEquals("Work", nameInfos[3].getLabel());
}
}
diff --git a/robolectric_tests/src/com/android/launcher3/logging/FileLogTest.java b/robolectric_tests/src/com/android/launcher3/logging/FileLogTest.java
index 48b5a45..95a4146 100644
--- a/robolectric_tests/src/com/android/launcher3/logging/FileLogTest.java
+++ b/robolectric_tests/src/com/android/launcher3/logging/FileLogTest.java
@@ -49,8 +49,9 @@
@After
public void tearDown() {
// Clear existing logs
- new File(mTempDir, "log-0").delete();
- new File(mTempDir, "log-1").delete();
+ for (int i = 0; i < FileLog.LOG_DAYS; i++) {
+ new File(mTempDir, "log-" + i).delete();
+ }
mTempDir.delete();
mTestActive = false;
@@ -89,8 +90,9 @@
Calendar threeDaysAgo = Calendar.getInstance();
threeDaysAgo.add(Calendar.HOUR, -72);
- new File(mTempDir, "log-0").setLastModified(threeDaysAgo.getTimeInMillis());
- new File(mTempDir, "log-1").setLastModified(threeDaysAgo.getTimeInMillis());
+ for (int i = 0; i < FileLog.LOG_DAYS; i++) {
+ new File(mTempDir, "log-" + i).setLastModified(threeDaysAgo.getTimeInMillis());
+ }
FileLog.print("Testing", "abracadabra", new Exception("cat! cat!"));
writer = new StringWriter();
diff --git a/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java b/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
index 50f9494..7072adf 100644
--- a/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
@@ -134,7 +134,7 @@
{ APP_ICON, SHORTCUT, SHORTCUT, NO__ICON},
}}, 2, OLD_WORK_PROFILE_ID);
// simulates the creation of backup upon restore
- new GridBackupTable(RuntimeEnvironment.application, mDb, mDb, mIdp.numHotseatIcons,
+ new GridBackupTable(RuntimeEnvironment.application, mDb, mIdp.numHotseatIcons,
mIdp.numColumns, mIdp.numRows).doBackup(
MY_OLD_PROFILE_ID, GridBackupTable.OPTION_REQUIRES_SANITIZATION);
// reset favorites table
diff --git a/robolectric_tests/src/com/android/launcher3/model/GridBackupTableTest.java b/robolectric_tests/src/com/android/launcher3/model/GridBackupTableTest.java
index 36fd96b..f46b849 100644
--- a/robolectric_tests/src/com/android/launcher3/model/GridBackupTableTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/GridBackupTableTest.java
@@ -63,7 +63,7 @@
@Test
public void backupTableCreated() {
- GridBackupTable backupTable = new GridBackupTable(mContext, mDb, mDb, 4, 4, 4);
+ GridBackupTable backupTable = new GridBackupTable(mContext, mDb, 4, 4, 4);
assertFalse(backupTable.backupOrRestoreAsNeeded());
Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
@@ -75,14 +75,14 @@
@Test
public void backupTableRestored() {
- assertFalse(new GridBackupTable(mContext, mDb, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
+ assertFalse(new GridBackupTable(mContext, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
// Delete entries
mDb.delete(TABLE_NAME, null, null);
assertEquals(0, queryNumEntries(mDb, TABLE_NAME));
- GridBackupTable backupTable = new GridBackupTable(mContext, mDb, mDb, 3, 3, 3);
+ GridBackupTable backupTable = new GridBackupTable(mContext, mDb, 3, 3, 3);
assertTrue(backupTable.backupOrRestoreAsNeeded());
// Items have been restored
@@ -96,7 +96,7 @@
@Test
public void backupTableRemovedOnAdd() {
- assertFalse(new GridBackupTable(mContext, mDb, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
+ assertFalse(new GridBackupTable(mContext, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
@@ -107,7 +107,7 @@
@Test
public void backupTableRemovedOnDelete() {
- assertFalse(new GridBackupTable(mContext, mDb, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
+ assertFalse(new GridBackupTable(mContext, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
@@ -118,7 +118,7 @@
@Test
public void backupTableRetainedOnUpdate() {
- assertFalse(new GridBackupTable(mContext, mDb, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
+ assertFalse(new GridBackupTable(mContext, mDb, 4, 4, 4).backupOrRestoreAsNeeded());
Settings.call(mContext.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index ac61c49..8718820 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -538,7 +538,7 @@
try {
dispatchRestoreInstanceState(states);
} catch (IllegalArgumentException ex) {
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
throw ex;
}
// Mismatched viewId / viewType preventing restore. Skip restore on production builds.
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index 466b7b2..f07040d 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -96,7 +96,7 @@
}
if (!(v.getParent() instanceof ShortcutAndWidgetContainer)) {
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
throw new IllegalStateException("Parent of the focused item is not supported.");
} else {
return false;
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index 787eee1..336e423 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -48,6 +48,8 @@
public static final int FLAG_MANUAL_FOLDER_NAME = 0x00000008;
+ public static final String EXTRA_FOLDER_SUGGESTIONS = "suggest";
+
public int options;
public Intent suggestedFolderNames;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 397a38b..3fc8de2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -482,7 +482,6 @@
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
- mAllAppsController.highlightWorkTabIfNecessary();
mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
}
@@ -2144,7 +2143,7 @@
Object tag = v.getTag();
String desc = "Collision while binding workspace item: " + item
+ ". Collides with " + tag;
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
throw (new RuntimeException(desc));
} else {
Log.d(TAG, desc);
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4cd038d..d77285d 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -91,7 +91,7 @@
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
mModelChangeReceiver.register(mContext, ACTION_FORCE_ROLOAD);
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index bb6c330..f618fe1 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -17,7 +17,7 @@
package com.android.launcher3;
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
-import static com.android.launcher3.config.FeatureFlags.IS_DOGFOOD_BUILD;
+import static com.android.launcher3.config.FeatureFlags.IS_STUDIO_BUILD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission;
@@ -55,7 +55,6 @@
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LooperExecutor;
@@ -67,7 +66,6 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
-import java.util.Optional;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
@@ -128,16 +126,6 @@
}
/**
- * Returns AppInfo with corresponding package name.
- * TODO: move to enqueueModelTask
- */
- public Optional<AppInfo> getAppInfoByPackageName(String pkg) {
- return mBgAllAppsList.data.stream()
- .filter(info -> info.componentName.getPackageName().equals(pkg))
- .findAny();
- }
-
- /**
* Adds the provided items to the workspace.
*/
public void addAndBindAddedWorkspaceItems(List<Pair<ItemInfo, Object>> itemList) {
@@ -250,7 +238,7 @@
enqueueModelUpdateTask(new UserLockStateChangedTask(user));
}
}
- } else if (IS_DOGFOOD_BUILD && ACTION_FORCE_ROLOAD.equals(action)) {
+ } else if (IS_STUDIO_BUILD && ACTION_FORCE_ROLOAD.equals(action)) {
for (Callbacks cb : getCallbacks()) {
if (cb instanceof Launcher) {
((Launcher) cb).recreate();
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 5544240..697048a 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -119,7 +119,7 @@
@Override
public boolean onCreate() {
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
Log.d(TAG, "Launcher process started");
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index ae4eae9..01893e9 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -374,6 +374,8 @@
protected void onPageEndTransition() {
mWasInOverscroll = false;
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
+ AccessibilityManagerCompat.sendCustomAccessibilityEvent(getPageAt(mCurrentPage),
+ AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
}
protected int getUnboundedScrollX() {
@@ -1502,7 +1504,7 @@
return false;
}
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
duration *= Settings.Global.getFloat(getContext().getContentResolver(),
Settings.Global.WINDOW_ANIMATION_SCALE, 1);
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index b7f8547..a8f492f 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1858,7 +1858,7 @@
CellLayout parentCell = getParentCellLayoutForView(cell);
if (parentCell != null) {
parentCell.removeView(cell);
- } else if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ } else if (FeatureFlags.IS_STUDIO_BUILD) {
throw new NullPointerException("mDragInfo.cell has null parent");
}
addInScreen(cell, container, screenId, mTargetCell[0], mTargetCell[1],
@@ -2153,7 +2153,7 @@
ItemInfo item = d.dragInfo;
if (item == null) {
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
throw new NullPointerException("DragObject has null info");
}
return;
@@ -2775,7 +2775,7 @@
mDragInfo.container, mDragInfo.screenId);
if (cellLayout != null) {
cellLayout.onDropChild(mDragInfo.cell);
- } else if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ } else if (FeatureFlags.IS_STUDIO_BUILD) {
throw new RuntimeException("Invalid state: cellLayout == null in "
+ "Workspace#onDropCompleted. Please file a bug. ");
}
@@ -2794,7 +2794,7 @@
CellLayout parentCell = getParentCellLayoutForView(v);
if (parentCell != null) {
parentCell.removeView(v);
- } else if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ } else if (FeatureFlags.IS_STUDIO_BUILD) {
// When an app is uninstalled using the drop target, we wait until resume to remove
// the icon. We also remove all the corresponding items from the workspace at
// {@link Launcher#bindComponentsRemoved}. That call can come before or after
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 56bd1b6..fcccc59 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -103,6 +103,8 @@
private final MultiValueAlpha mMultiValueAlpha;
+ Rect mInsets = new Rect();
+
public AllAppsContainerView(Context context) {
this(context, null);
}
@@ -153,6 +155,11 @@
return mMultiValueAlpha.getProperty(index);
}
+ public WorkFooterContainer getWorkFooterContainer() {
+ return mWorkFooterContainer;
+ }
+
+
@Override
protected void setDampedScrollShift(float shift) {
// Bound the shift amount to avoid content from drawing on top (Y-val) of the QSB.
@@ -320,6 +327,7 @@
@Override
public void setInsets(Rect insets) {
+ mInsets.set(insets);
DeviceProfile grid = mLauncher.getDeviceProfile();
int leftRightPadding = grid.desiredWorkspaceLeftRightMarginPx
+ grid.cellLayoutPaddingLeftRightPx;
@@ -411,6 +419,7 @@
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
this.addView(mWorkFooterContainer);
+ mWorkFooterContainer.setInsets(mInsets);
mWorkFooterContainer.post(() -> mAH[AdapterHolder.WORK].applyPadding());
}
@@ -548,17 +557,6 @@
return mHeader != null && mHeader.getVisibility() == View.VISIBLE;
}
- public void onScrollUpEnd() {
- highlightWorkTabIfNecessary();
- }
-
- void highlightWorkTabIfNecessary() {
- if (mUsingTabs) {
- ((PersonalWorkSlidingTabStrip) findViewById(R.id.tabs))
- .highlightWorkTabIfNecessary();
- }
- }
-
/**
* Adds an update listener to {@param animator} that adds springs to the animation.
*/
@@ -643,9 +641,9 @@
R.layout.work_apps_paused, null);
recyclerView.post(() -> {
int width = recyclerView.getWidth();
- int height = recyclerView.getHeight();
- pausedOverlay.measure(makeMeasureSpec(width, EXACTLY),
- makeMeasureSpec(height, EXACTLY));
+ int height = recyclerView.getHeight() - mWorkFooterContainer.getHeight();
+ pausedOverlay.measure(makeMeasureSpec(recyclerView.getWidth(), EXACTLY),
+ makeMeasureSpec(recyclerView.getHeight(), EXACTLY));
pausedOverlay.layout(0, 0, width, height);
applyPadding();
});
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 93bdac9..6aa3efc 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -248,18 +248,6 @@
private void onProgressAnimationEnd() {
if (Float.compare(mProgress, 1f) == 0) {
mAppsView.reset(false /* animate */);
- } else if (isAllAppsExpanded()) {
- mAppsView.onScrollUpEnd();
- }
- }
-
- private boolean isAllAppsExpanded() {
- return Float.compare(mProgress, 0f) == 0;
- }
-
- public void highlightWorkTabIfNecessary() {
- if (isAllAppsExpanded()) {
- mAppsView.highlightWorkTabIfNecessary();
}
}
}
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index e8035eb..0f0fc3a 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -35,7 +35,6 @@
import com.android.launcher3.LauncherStateManager.StateListener;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.pm.UserCache;
/**
* Abstract base class of floating view responsible for showing discovery bounce animation
@@ -144,8 +143,7 @@
private static void showForHomeIfNeeded(Launcher launcher, boolean withDelay) {
if (!launcher.isInState(NORMAL)
- || (launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)
- && !shouldShowForWorkProfile(launcher))
+ || launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)
|| AbstractFloatingView.getTopOpenView(launcher) != null
|| launcher.getSystemService(UserManager.class).isDemoUser()
|| Utilities.IS_RUNNING_IN_TEST_HARNESS) {
@@ -170,8 +168,7 @@
|| !launcher.hasBeenResumed()
|| launcher.isForceInvisible()
|| launcher.getDeviceProfile().isVerticalBarLayout()
- || (launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)
- && !shouldShowForWorkProfile(launcher))
+ || launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)
|| launcher.getSystemService(UserManager.class).isDemoUser()
|| Utilities.IS_RUNNING_IN_TEST_HARNESS) {
return;
@@ -213,12 +210,6 @@
}
}
- private static boolean shouldShowForWorkProfile(Launcher launcher) {
- return !launcher.getSharedPrefs().getBoolean(
- PersonalWorkSlidingTabStrip.KEY_SHOWED_PEEK_WORK_TAB, false)
- && UserCache.INSTANCE.get(launcher).hasWorkProfile();
- }
-
private static void incrementShelfBounceCount(Launcher launcher) {
SharedPreferences sharedPrefs = launcher.getSharedPrefs();
int count = sharedPrefs.getInt(SHELF_BOUNCE_COUNT, 0);
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index 9d0ecd3..25db0e7 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -64,6 +64,14 @@
}
@Override
+ public void setupHeader() {
+ super.setupHeader();
+ if (mWorkTabListener != null && !mUsingTabs) {
+ mLauncher.getStateManager().removeStateListener(mWorkTabListener);
+ }
+ }
+
+ @Override
public void onTabChanged(int pos) {
super.onTabChanged(pos);
if (mUsingTabs) {
diff --git a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
index 6204f31..0e39bbe 100644
--- a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
@@ -16,7 +16,6 @@
package com.android.launcher3.allapps;
import android.content.Context;
-import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
@@ -39,11 +38,8 @@
private static final int POSITION_PERSONAL = 0;
private static final int POSITION_WORK = 1;
- public static final String KEY_SHOWED_PEEK_WORK_TAB = "showed_peek_work_tab";
-
private final Paint mSelectedIndicatorPaint;
private final Paint mDividerPaint;
- private final SharedPreferences mSharedPreferences;
private int mSelectedIndicatorHeight;
private int mIndicatorLeft = -1;
@@ -72,7 +68,6 @@
mDividerPaint.setStrokeWidth(
getResources().getDimensionPixelSize(R.dimen.all_apps_divider_height));
- mSharedPreferences = Utilities.getPrefs(context);
mIsRtl = Utilities.isRtl(getResources());
}
@@ -128,25 +123,6 @@
mIndicatorRight, getHeight(), mSelectedIndicatorPaint);
}
- public void highlightWorkTabIfNecessary() {
- if (mSharedPreferences.getBoolean(KEY_SHOWED_PEEK_WORK_TAB, false)) {
- return;
- }
- if (mLastActivePage != POSITION_PERSONAL) {
- return;
- }
- highlightWorkTab();
- mSharedPreferences.edit().putBoolean(KEY_SHOWED_PEEK_WORK_TAB, true).apply();
- }
-
- private void highlightWorkTab() {
- View v = getChildAt(POSITION_WORK);
- v.post(() -> {
- v.setPressed(true);
- v.setPressed(false);
- });
- }
-
@Override
public void setScroll(int currentScroll, int totalScroll) {
float scrollOffset = ((float) currentScroll) / totalScroll;
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 28579c1..db4bef0 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -18,11 +18,14 @@
import android.content.Context;
import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.Utilities;
import com.android.launcher3.testing.TestProtocol;
@@ -37,11 +40,13 @@
return isAccessibilityEnabled(context);
}
- public static void sendCustomAccessibilityEvent(View target, int type, String text) {
+ public static void sendCustomAccessibilityEvent(View target, int type, @Nullable String text) {
if (isObservedEventType(target.getContext(), type)) {
AccessibilityEvent event = AccessibilityEvent.obtain(type);
target.onInitializeAccessibilityEvent(event);
- event.getText().add(text);
+ if (!TextUtils.isEmpty(text)) {
+ event.getText().add(text);
+ }
getManager(target.getContext()).sendAccessibilityEvent(event);
}
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index cc33965..6413044 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -22,6 +22,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.uioverrides.DeviceFlag;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -42,7 +43,10 @@
return Utilities.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context);
}
- public static final boolean IS_DOGFOOD_BUILD = BuildConfig.DEBUG;
+ /**
+ * True when the build has come from Android Studio and is being used for local debugging.
+ */
+ public static final boolean IS_STUDIO_BUILD = BuildConfig.DEBUG;
/**
* Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature
@@ -90,13 +94,13 @@
"FAKE_LANDSCAPE_UI", false, "Rotate launcher UI instead of using transposed layout");
public static final BooleanFlag FOLDER_NAME_SUGGEST = getDebugFlag(
- "FOLDER_NAME_SUGGEST", false, "Suggests folder names instead of blank text.");
+ "FOLDER_NAME_SUGGEST", true, "Suggests folder names instead of blank text.");
public static final BooleanFlag APP_SEARCH_IMPROVEMENTS = new DeviceFlag(
"APP_SEARCH_IMPROVEMENTS", false,
"Adds localized title and keyword search and ranking");
- public static final BooleanFlag ENABLE_PREDICTION_DISMISS = getDebugFlag(
+ public static final BooleanFlag ENABLE_PREDICTION_DISMISS = new DeviceFlag(
"ENABLE_PREDICTION_DISMISS", false, "Allow option to dimiss apps from predicted list");
public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
@@ -106,7 +110,7 @@
"ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
"Allow Launcher to handle nav bar gestures while Assistant is running over it");
- public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = getDebugFlag(
+ public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = new DeviceFlag(
"ENABLE_HYBRID_HOTSEAT", false, "Fill gaps in hotseat with predicted apps");
public static final BooleanFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = getDebugFlag(
@@ -145,6 +149,15 @@
}
}
+ public static void dump(PrintWriter pw) {
+ pw.println("FeatureFlags:");
+ synchronized (sDebugFlags) {
+ for (DebugFlag flag : sDebugFlags) {
+ pw.println(" " + flag.key + "=" + flag.get());
+ }
+ }
+ }
+
public static class BooleanFlag {
public final String key;
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 1b7b015..de7bc6d 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -160,8 +160,8 @@
mOptions = options;
if (mOptions.systemDndStartPoint != null) {
- mMotionDownX = mOptions.systemDndStartPoint.x;
- mMotionDownY = mOptions.systemDndStartPoint.y;
+ mLastTouch[0] = mMotionDownX = mOptions.systemDndStartPoint.x;
+ mLastTouch[1] = mMotionDownY = mOptions.systemDndStartPoint.y;
}
final int registrationX = mMotionDownX - dragLayerX;
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 8e80916..c72509e 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -16,9 +16,23 @@
package com.android.launcher3.folder;
+import static android.text.TextUtils.isEmpty;
+
+import static androidx.core.util.Preconditions.checkNotNull;
+
+import static com.android.launcher3.FolderInfo.FLAG_MANUAL_FOLDER_NAME;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
+import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_CUSTOM;
+import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_EMPTY;
+import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_FOLDER_LABEL_STATE_UNSPECIFIED;
+import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_SUGGESTED;
+
+import static java.util.Arrays.asList;
+import static java.util.Arrays.stream;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -75,20 +89,24 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.logging.LoggerUtils;
import com.android.launcher3.pageindicators.PageIndicatorDots;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
+import com.android.launcher3.userevent.LauncherLogProto.Action;
+import com.android.launcher3.userevent.LauncherLogProto.ContainerType;
+import com.android.launcher3.userevent.LauncherLogProto.ItemType;
+import com.android.launcher3.userevent.LauncherLogProto.LauncherEvent;
+import com.android.launcher3.userevent.LauncherLogProto.Target;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ClipPathView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
/**
* Represents a set of icons chosen by the user or generated by the system.
@@ -186,6 +204,9 @@
@Thunk int mScrollHintDir = SCROLL_NONE;
@Thunk int mCurrentScrollDir = SCROLL_NONE;
+ private String mPreviousLabel;
+ private boolean mIsPreviousLabelSuggested;
+
/**
* Used to inflate the Workspace from XML.
*
@@ -300,13 +321,13 @@
public void startEditingFolderName() {
post(() -> {
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
- if (TextUtils.isEmpty(mFolderName.getText())) {
- String[] suggestedNames =
- mInfo.suggestedFolderNames.getStringArrayExtra("suggest");
- mFolderName.setText(suggestedNames[0]);
- mFolderName.displayCompletions(Arrays.asList(suggestedNames).subList(1,
- suggestedNames.length));
- mFolderName.setEnteredCompose(false);
+ if (isEmpty(mFolderName.getText())) {
+ FolderNameInfo[] nameInfos =
+ (FolderNameInfo[]) mInfo.suggestedFolderNames.getParcelableArrayExtra(
+ FolderInfo.EXTRA_FOLDER_SUGGESTIONS);
+ if (nameInfos != null) {
+ showLabelSuggestion(nameInfos, false);
+ }
}
}
mFolderName.setHint("");
@@ -324,23 +345,16 @@
}
mInfo.title = newTitle;
- mInfo.setOption(FolderInfo.FLAG_MANUAL_FOLDER_NAME, mFolderName.isEnteredCompose(),
+ mInfo.setOption(FLAG_MANUAL_FOLDER_NAME, mFolderName.isEnteredCompose(),
mLauncher.getModelWriter());
mFolderIcon.onTitleChanged(newTitle);
mLauncher.getModelWriter().updateItemInDatabase(mInfo);
- if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
- mFolderName.setText(mInfo.title);
- // TODO: depending on whether the title was manually edited or automatically
- // suggested, apply different hint.
- mFolderName.setHint("");
+ if (TextUtils.isEmpty(mInfo.title)) {
+ mFolderName.setHint(R.string.folder_hint_text);
+ mFolderName.setText("");
} else {
- if (TextUtils.isEmpty(mInfo.title)) {
- mFolderName.setHint(R.string.folder_hint_text);
- mFolderName.setText("");
- } else {
- mFolderName.setHint(null);
- }
+ mFolderName.setHint(null);
}
sendCustomAccessibilityEvent(
@@ -423,8 +437,10 @@
mItemsInvalidated = true;
mInfo.addListener(this);
- if (!TextUtils.isEmpty(mInfo.title)) {
+ if (!isEmpty(mInfo.title)) {
mFolderName.setText(mInfo.title);
+ mPreviousLabel = mInfo.title.toString();
+ mIsPreviousLabelSuggested = !mInfo.hasOption(FLAG_MANUAL_FOLDER_NAME);
mFolderName.setHint(null);
} else {
mFolderName.setText("");
@@ -443,27 +459,54 @@
}
/**
- * Show suggested folder title.
+ * Show suggested folder title in FolderEditText, push InputMethodManager suggestions and save
+ * the suggestedFolderNames.
*/
- public void showSuggestedTitle(String[] suggestName) {
+ public void showSuggestedTitle(FolderNameInfo[] nameInfos) {
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
- mInfo.suggestedFolderNames = new Intent().putExtra("suggest", suggestName);
- if (TextUtils.isEmpty(mFolderName.getText().toString())
- && !mInfo.hasOption(FolderInfo.FLAG_MANUAL_FOLDER_NAME)) {
- if (suggestName.length > 0 && !TextUtils.isEmpty(suggestName[0])) {
- mFolderName.setHint("");
- mFolderName.setText(suggestName[0]);
- mInfo.title = suggestName[0];
- animateOpen(mInfo.contents, 0, true);
- mFolderName.showKeyboard();
- mFolderName.displayCompletions(
- Arrays.asList(suggestName).subList(1, suggestName.length));
- }
+ mInfo.suggestedFolderNames = new Intent().putExtra(FolderInfo.EXTRA_FOLDER_SUGGESTIONS,
+ nameInfos);
+ if (isEmpty(mFolderName.getText().toString())
+ && !mInfo.hasOption(FLAG_MANUAL_FOLDER_NAME)) {
+ showLabelSuggestion(nameInfos, true);
}
}
}
/**
+ * Show suggested folder title in FolderEditText if the first suggestion is non-empty, push
+ * InputMethodManager suggestions.
+ */
+ private void showLabelSuggestion(FolderNameInfo[] nameInfos, boolean animate) {
+ if (nameInfos == null) {
+ return;
+ }
+ // Open the Folder and Keyboard when the first or second suggestion is valid non-empty
+ // string.
+ boolean shouldOpen = nameInfos.length > 0 && nameInfos[0] != null && !isEmpty(
+ nameInfos[0].getLabel())
+ || nameInfos.length > 1 && nameInfos[1] != null && !isEmpty(
+ nameInfos[1].getLabel());
+
+ if (shouldOpen) {
+ CharSequence firstLabel = nameInfos[0] == null ? "" : nameInfos[0].getLabel();
+ if (!isEmpty(firstLabel)) {
+ mFolderName.setHint("");
+ mFolderName.setText(firstLabel);
+ }
+ if (animate) {
+ animateOpen(mInfo.contents, 0, true);
+ }
+ mFolderName.showKeyboard();
+ mFolderName.displayCompletions(
+ asList(nameInfos).subList(1, nameInfos.length).stream()
+ .filter(Objects::nonNull)
+ .map(s -> s.getLabel().toString())
+ .collect(Collectors.toList()));
+ }
+ }
+
+ /**
* Creates a new UserFolder, inflated from R.layout.user_folder.
*
* @param launcher The main activity.
@@ -580,7 +623,7 @@
dragLayer.addView(this);
mDragController.addDropTarget(this);
} else {
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
Log.e(TAG, "Opening folder (" + this + ") which already has a parent:"
+ getParent());
}
@@ -608,9 +651,9 @@
if (!skipUserEventLog) {
mLauncher.getUserEventDispatcher().logActionOnItem(
- Touch.TAP,
- Direction.NONE,
- ItemType.FOLDER_ICON, mInfo.cellX, mInfo.cellY);
+ LauncherLogProto.Action.Touch.TAP,
+ LauncherLogProto.Action.Direction.NONE,
+ LauncherLogProto.ItemType.FOLDER_ICON, mInfo.cellX, mInfo.cellY);
}
@@ -1392,6 +1435,7 @@
if (hasFocus) {
startEditingFolderName();
} else {
+ logEditFolderLabel();
mFolderName.dispatchBackKey();
}
}
@@ -1405,11 +1449,12 @@
}
@Override
- public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
+ public void fillInLogContainerData(View v, ItemInfo info, LauncherLogProto.Target target,
+ LauncherLogProto.Target targetParent) {
target.gridX = info.cellX;
target.gridY = info.cellY;
target.pageIndex = mContent.getCurrentPage();
- targetParent.containerType = ContainerType.FOLDER;
+ targetParent.containerType = LauncherLogProto.ContainerType.FOLDER;
}
private class OnScrollHintListener implements OnAlarmListener {
@@ -1507,7 +1552,7 @@
@Override
public int getLogContainerType() {
- return ContainerType.FOLDER;
+ return LauncherLogProto.ContainerType.FOLDER;
}
/**
@@ -1542,7 +1587,7 @@
}
} else {
mLauncher.getUserEventDispatcher().logActionTapOutside(
- LoggerUtils.newContainerTarget(ContainerType.FOLDER));
+ LoggerUtils.newContainerTarget(LauncherLogProto.ContainerType.FOLDER));
close(true);
return true;
}
@@ -1572,4 +1617,113 @@
super.draw(canvas);
}
}
+
+ private void logEditFolderLabel() {
+ LauncherEvent launcherEvent = LauncherEvent.newBuilder()
+ .setAction(Action.newBuilder().setType(Action.Type.SOFT_KEYBOARD))
+ .addSrcTarget(newEditTextTargetBuilder()
+ .setFromFolderLabelState(getFromFolderLabelState())
+ .setToFolderLabelState(getToFolderLabelState()))
+ .addSrcTarget(newFolderTargetBuilder())
+ .addSrcTarget(newParentContainerTarget())
+ .build();
+ mLauncher.getUserEventDispatcher().logLauncherEvent(launcherEvent);
+ mPreviousLabel = mFolderName.getText().toString();
+ mIsPreviousLabelSuggested = !mInfo.hasOption(FLAG_MANUAL_FOLDER_NAME);
+ }
+
+ private Target.FromFolderLabelState getFromFolderLabelState() {
+ return mPreviousLabel == null
+ ? FROM_FOLDER_LABEL_STATE_UNSPECIFIED
+ : mPreviousLabel.isEmpty()
+ ? FROM_EMPTY
+ : mIsPreviousLabelSuggested
+ ? FROM_SUGGESTED
+ : FROM_CUSTOM;
+ }
+
+ private Target.ToFolderLabelState getToFolderLabelState() {
+ String newLabel =
+ checkNotNull(mFolderName.getText().toString(),
+ "Expected valid folder label, but found null");
+
+ Optional<String[]> suggestedLabels = Optional.ofNullable(
+ (FolderNameInfo[]) mInfo.suggestedFolderNames
+ .getParcelableArrayExtra(FolderInfo.EXTRA_FOLDER_SUGGESTIONS))
+ .map(folderNameInfoArray ->
+ stream(folderNameInfoArray)
+ .filter(Objects::nonNull)
+ .map(FolderNameInfo::getLabel)
+ .map(CharSequence::toString)
+ .toArray(String[]::new));
+
+
+ int accepted_suggestion_index = suggestedLabels
+ .map(folderNameInfoArray ->
+ IntStream.range(0, folderNameInfoArray.length)
+ .filter(index -> newLabel.equalsIgnoreCase(
+ folderNameInfoArray[index]))
+ .findFirst()
+ .orElse(-1)
+ ).orElse(-1);
+
+ boolean hasValidPrimary = suggestedLabels
+ .map(labels -> labels.length > 0 && !isEmpty(labels[0]))
+ .orElse(false);
+ String primarySuffix = hasValidPrimary
+ ? "_WITH_VALID_PRIMARY"
+ : "_WITH_EMPTY_PRIMARY";
+
+ boolean isEmptySuggestions = suggestedLabels
+ .map(labels -> stream(labels).allMatch(TextUtils::isEmpty))
+ .orElse(true);
+ boolean isSuggestionsEnabled = FeatureFlags.FOLDER_NAME_SUGGEST.get();
+ String suggestionsSuffix = isSuggestionsEnabled
+ ? isEmptySuggestions
+ ? "_WITH_EMPTY_SUGGESTIONS"
+ : "_WITH_VALID_SUGGESTIONS"
+ : "_WITH_SUGGESTIONS_DISABLED";
+
+ return newLabel.equals(mPreviousLabel)
+ ? Target.ToFolderLabelState.UNCHANGED
+ : newLabel.isEmpty()
+ ? Target.ToFolderLabelState.valueOf("TO_EMPTY" + suggestionsSuffix)
+ : accepted_suggestion_index >= 0
+ ? Target.ToFolderLabelState.valueOf("TO_SUGGESTION"
+ + accepted_suggestion_index
+ + primarySuffix)
+ : Target.ToFolderLabelState.valueOf("TO_CUSTOM" + suggestionsSuffix);
+ }
+
+
+ private Target.Builder newEditTextTargetBuilder() {
+ return Target.newBuilder().setType(Target.Type.ITEM).setItemType(ItemType.EDITTEXT);
+ }
+
+ private Target.Builder newFolderTargetBuilder() {
+ return Target.newBuilder()
+ .setType(Target.Type.CONTAINER)
+ .setContainerType(ContainerType.FOLDER)
+ .setPageIndex(mInfo.screenId)
+ .setGridX(mInfo.cellX)
+ .setGridY(mInfo.cellY)
+ .setCardinality(mInfo.contents.size());
+ }
+
+ private Target.Builder newParentContainerTarget() {
+ Target.Builder builder = Target.newBuilder().setType(Target.Type.CONTAINER);
+
+ switch (mInfo.container) {
+ case CONTAINER_HOTSEAT:
+ return builder.setContainerType(ContainerType.HOTSEAT);
+ case CONTAINER_DESKTOP:
+ return builder.setContainerType(ContainerType.WORKSPACE);
+ default:
+ throw new AssertionError(String
+ .format("Expected container to be either %s or %s but found %s.",
+ CONTAINER_HOTSEAT,
+ CONTAINER_DESKTOP,
+ mInfo.container));
+ }
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 6a47b98..ab1ff10 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -393,15 +393,16 @@
if (!itemAdded) mPreviewItemManager.hidePreviewItem(index, true);
final int finalIndex = index;
- String[] suggestedNameOut = new String[FolderNameProvider.SUGGEST_MAX];
+ FolderNameInfo[] nameInfos =
+ new FolderNameInfo[FolderNameProvider.SUGGEST_MAX];
if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
Executors.UI_HELPER_EXECUTOR.post(() -> {
d.folderNameProvider.getSuggestedFolderName(
- getContext(), mInfo.contents, suggestedNameOut);
- showFinalView(finalIndex, item, suggestedNameOut);
+ getContext(), mInfo.contents, nameInfos);
+ showFinalView(finalIndex, item, nameInfos);
});
} else {
- showFinalView(finalIndex, item, suggestedNameOut);
+ showFinalView(finalIndex, item, nameInfos);
}
} else {
addItem(item);
@@ -409,12 +410,12 @@
}
private void showFinalView(int finalIndex, final WorkspaceItemInfo item,
- String[] suggestedNameOut) {
+ FolderNameInfo[] nameInfos) {
postDelayed(() -> {
mPreviewItemManager.hidePreviewItem(finalIndex, false);
mFolder.showItem(item);
invalidate();
- mFolder.showSuggestedTitle(suggestedNameOut);
+ mFolder.showSuggestedTitle(nameInfos);
}, DROP_IN_ANIMATION_DURATION);
}
diff --git a/src/com/android/launcher3/folder/FolderNameInfo.java b/src/com/android/launcher3/folder/FolderNameInfo.java
new file mode 100644
index 0000000..ecbe46c
--- /dev/null
+++ b/src/com/android/launcher3/folder/FolderNameInfo.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 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.folder;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Information about a single label suggestions of the Folder.
+ */
+
+public final class FolderNameInfo implements Parcelable {
+ private final double mScore;
+ private final CharSequence mLabel;
+
+ /**
+ * Create a simple completion with label.
+ *
+ * @param label The text that should be inserted into the editor and pushed to
+ * InputMethodManager suggestions.
+ * @param score The score for the label between 0.0 and 1.0.
+ */
+ public FolderNameInfo(CharSequence label, double score) {
+ mScore = score;
+ mLabel = label;
+ }
+
+ private FolderNameInfo(Parcel source) {
+ mScore = source.readDouble();
+ mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ }
+
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * Used to package this object into a {@link Parcel}.
+ *
+ * @param dest The {@link Parcel} to be written.
+ * @param flags The flags used for parceling.
+ */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeDouble(mScore);
+ TextUtils.writeToParcel(mLabel, dest, flags);
+ }
+
+ /**
+ * Used to make this class parcelable.
+ */
+ @NonNull
+ public static final Parcelable.Creator<FolderNameInfo> CREATOR =
+ new Parcelable.Creator<FolderNameInfo>() {
+ public FolderNameInfo createFromParcel(Parcel source) {
+ return new FolderNameInfo(source);
+ }
+
+ public FolderNameInfo[] newArray(int size) {
+ return new FolderNameInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return mLabel.toString() + ":" + mScore;
+ }
+}
diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java
index 957e636..184dbb9 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -21,15 +21,21 @@
import android.util.Log;
import com.android.launcher3.AppInfo;
+import com.android.launcher3.FolderInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
+import com.android.launcher3.model.AllAppsList;
+import com.android.launcher3.model.BaseModelUpdateTask;
+import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.util.IntSparseArrayMap;
import com.android.launcher3.util.ResourceBasedOverride;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
@@ -49,6 +55,8 @@
* name edit box can also be used to provide suggestion.
*/
public static final int SUGGEST_MAX = 4;
+ protected IntSparseArrayMap<FolderInfo> mFolderInfos;
+ protected List<AppInfo> mAppInfos;
/**
* Retrieve instance of this object that can be overridden in runtime based on the build
@@ -57,78 +65,113 @@
public static FolderNameProvider newInstance(Context context) {
FolderNameProvider fnp = Overrides.getObject(FolderNameProvider.class,
context.getApplicationContext(), R.string.folder_name_provider_class);
+ fnp.load(context);
+
return fnp;
}
- public CharSequence getSuggestedFolderName(Context context,
- ArrayList<WorkspaceItemInfo> workspaceItemInfos, CharSequence[] candidates) {
+ public static FolderNameProvider newInstance(Context context, List<AppInfo> appInfos,
+ IntSparseArrayMap<FolderInfo> folderInfos) {
+ FolderNameProvider fnp = Overrides.getObject(FolderNameProvider.class,
+ context.getApplicationContext(), R.string.folder_name_provider_class);
+ fnp.load(appInfos, folderInfos);
+
+ return fnp;
+ }
+
+ private void load(Context context) {
+ LauncherAppState.getInstance(context).getModel().enqueueModelUpdateTask(
+ new FolderNameWorker());
+ }
+
+ private void load(List<AppInfo> appInfos, IntSparseArrayMap<FolderInfo> folderInfos) {
+ mAppInfos = appInfos;
+ mFolderInfos = folderInfos;
+ }
+
+ /**
+ * Generate and rank the suggested Folder names.
+ */
+ public void getSuggestedFolderName(Context context,
+ ArrayList<WorkspaceItemInfo> workspaceItemInfos,
+ FolderNameInfo[] nameInfos) {
if (DEBUG) {
- Log.d(TAG, "getSuggestedFolderName:" + Arrays.toString(candidates));
+ Log.d(TAG, "getSuggestedFolderName:" + Arrays.toString(nameInfos));
}
// If all the icons are from work profile,
// Then, suggest "Work" as the folder name
List<WorkspaceItemInfo> distinctItemInfos = workspaceItemInfos.stream()
- .filter(distinctByKey(p-> p.user))
+ .filter(distinctByKey(p -> p.user))
.collect(Collectors.toList());
if (distinctItemInfos.size() == 1
&& !distinctItemInfos.get(0).user.equals(Process.myUserHandle())) {
// Place it as last viable suggestion
- setAsLastSuggestion(candidates,
+ setAsLastSuggestion(nameInfos,
context.getResources().getString(R.string.work_folder_name));
}
// If all the icons are from same package (e.g., main icon, shortcut, shortcut)
// Then, suggest the package's title as the folder name
distinctItemInfos = workspaceItemInfos.stream()
- .filter(distinctByKey(p-> p.getTargetComponent() != null
+ .filter(distinctByKey(p -> p.getTargetComponent() != null
? p.getTargetComponent().getPackageName() : ""))
.collect(Collectors.toList());
if (distinctItemInfos.size() == 1) {
- Optional<AppInfo> info = LauncherAppState.getInstance(context).getModel()
- .getAppInfoByPackageName(distinctItemInfos.get(0).getTargetComponent()
- .getPackageName());
+ Optional<AppInfo> info = getAppInfoByPackageName(
+ distinctItemInfos.get(0).getTargetComponent().getPackageName());
// Place it as first viable suggestion and shift everything else
- info.ifPresent(i -> setAsFirstSuggestion(candidates, i.title.toString()));
+ info.ifPresent(i -> setAsFirstSuggestion(nameInfos, i.title.toString()));
}
if (DEBUG) {
- Log.d(TAG, "getSuggestedFolderName:" + Arrays.toString(candidates));
+ Log.d(TAG, "getSuggestedFolderName:" + Arrays.toString(nameInfos));
}
- return candidates[0];
}
- private void setAsFirstSuggestion(CharSequence[] candidatesOut, CharSequence candidate) {
- if (contains(candidatesOut, candidate)) {
+ private Optional<AppInfo> getAppInfoByPackageName(String packageName) {
+ if (mAppInfos == null || mAppInfos.isEmpty()) {
+ return Optional.empty();
+ }
+ return mAppInfos.stream()
+ .filter(info -> info.componentName.getPackageName().equals(packageName))
+ .findAny();
+ }
+
+ private void setAsFirstSuggestion(FolderNameInfo[] nameInfos, CharSequence label) {
+ if (nameInfos.length == 0 || contains(nameInfos, label)) {
return;
}
- for (int i = candidatesOut.length - 1; i > 0; i--) {
- if (!TextUtils.isEmpty(candidatesOut[i - 1])) {
- candidatesOut[i] = candidatesOut[i - 1];
+ for (int i = nameInfos.length - 1; i > 0; i--) {
+ if (nameInfos[i - 1] != null && !TextUtils.isEmpty(nameInfos[i - 1].getLabel())) {
+ nameInfos[i] = nameInfos[i - 1];
}
}
- candidatesOut[0] = candidate;
+ nameInfos[0] = new FolderNameInfo(label, 1.0);
}
- private void setAsLastSuggestion(CharSequence[] candidatesOut, CharSequence candidate) {
- if (contains(candidatesOut, candidate)) {
+ private void setAsLastSuggestion(FolderNameInfo[] nameInfos, CharSequence label) {
+ if (nameInfos.length == 0 || contains(nameInfos, label)) {
return;
}
- for (int i = 0; i < candidate.length(); i++) {
- if (TextUtils.isEmpty(candidatesOut[i])) {
- candidatesOut[i] = candidate;
+ for (int i = 0; i < nameInfos.length; i++) {
+ if (nameInfos[i] == null || TextUtils.isEmpty(nameInfos[i].getLabel())) {
+ nameInfos[i] = new FolderNameInfo(label, 1.0);
return;
}
}
- candidatesOut[candidate.length() - 1] = candidate;
+ // Overwrite the last suggestion.
+ int lastIndex = nameInfos.length - 1;
+ nameInfos[lastIndex] = new FolderNameInfo(label, 1.0);
}
- private boolean contains(CharSequence[] list, CharSequence key) {
- return Arrays.asList(list).stream()
- .filter(s -> s != null)
- .anyMatch(s -> s.toString().equalsIgnoreCase(key.toString()));
+ private boolean contains(FolderNameInfo[] nameInfos, CharSequence label) {
+ return Arrays.stream(nameInfos)
+ .filter(Objects::nonNull)
+ .anyMatch(nameInfo -> nameInfo.getLabel().toString().equalsIgnoreCase(
+ label.toString()));
}
// This method can be moved to some Utility class location.
@@ -136,4 +179,13 @@
Map<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
+
+ private class FolderNameWorker extends BaseModelUpdateTask {
+ @Override
+ public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
+ mFolderInfos = dataModel.folders.clone();
+ mAppInfos = Arrays.asList(apps.copyData());
+ }
+ }
+
}
diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index f579451..94d30f6 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -152,7 +152,7 @@
}
public final void generateDragOutline(Bitmap preview) {
- if (FeatureFlags.IS_DOGFOOD_BUILD && mOutlineGeneratorCallback != null) {
+ if (FeatureFlags.IS_STUDIO_BUILD && mOutlineGeneratorCallback != null) {
throw new RuntimeException("Drag outline generated twice");
}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index def76e8..a429af2 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -25,6 +25,7 @@
import android.annotation.TargetApi;
import android.app.Fragment;
+import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -55,6 +56,7 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -72,6 +74,8 @@
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.LoaderResults;
+import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
@@ -248,6 +252,16 @@
addInScreenFromBind(folderIcon, info);
}
+ private void inflateAndAddWidgets(LauncherAppWidgetInfo info, WidgetsModel widgetsModel) {
+ WidgetItem widgetItem = widgetsModel.getWidgetProviderInfoByProviderName(
+ info.providerName);
+ AppWidgetHostView view = new AppWidgetHostView(mContext);
+ view.setAppWidget(-1, widgetItem.widgetInfo);
+ view.updateAppWidget(null);
+ view.setTag(info);
+ addInScreenFromBind(view, info);
+ }
+
private void dispatchVisibilityAggregated(View view, boolean isVisible) {
// Similar to View.dispatchVisibilityAggregated implementation.
final boolean thisVisible = view.getVisibility() == VISIBLE;
@@ -272,9 +286,9 @@
mContext).getModel();
final WorkspaceItemsInfoFetcher fetcher = new WorkspaceItemsInfoFetcher();
launcherModel.enqueueModelUpdateTask(fetcher);
- ArrayList<ItemInfo> workspaceItems;
+ WorkspaceResult workspaceResult;
try {
- workspaceItems = fetcher.mTask.get(5, TimeUnit.SECONDS);
+ workspaceResult = fetcher.mTask.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Log.d(TAG, "Error fetching workspace items info", e);
return;
@@ -284,9 +298,14 @@
// items
ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>();
ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>();
+ ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<>();
+ ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<>();
- filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceItems,
- currentWorkspaceItems, otherWorkspaceItems);
+ filterCurrentWorkspaceItems(0 /* currentScreenId */,
+ workspaceResult.mWorkspaceItems, currentWorkspaceItems,
+ otherWorkspaceItems);
+ filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceResult.mAppWidgets,
+ currentAppWidgets, otherAppWidgets);
sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems);
for (ItemInfo itemInfo : currentWorkspaceItems) {
@@ -303,6 +322,17 @@
break;
}
}
+ for (ItemInfo itemInfo : currentAppWidgets) {
+ switch (itemInfo.itemType) {
+ case Favorites.ITEM_TYPE_APPWIDGET:
+ case Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
+ inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
+ workspaceResult.mWidgetsModel);
+ break;
+ default:
+ break;
+ }
+ }
} else {
// Add hotseat icons
for (int i = 0; i < mIdp.numHotseatIcons; i++) {
@@ -349,10 +379,10 @@
}
}
- private static class WorkspaceItemsInfoFetcher implements Callable<ArrayList<ItemInfo>>,
+ private static class WorkspaceItemsInfoFetcher implements Callable<WorkspaceResult>,
LauncherModel.ModelUpdateTask {
- private final FutureTask<ArrayList<ItemInfo>> mTask = new FutureTask<>(this);
+ private final FutureTask<WorkspaceResult> mTask = new FutureTask<>(this);
private LauncherAppState mApp;
private LauncherModel mModel;
@@ -374,14 +404,16 @@
}
@Override
- public ArrayList<ItemInfo> call() throws Exception {
+ public WorkspaceResult call() throws Exception {
if (!mModel.isModelLoaded()) {
Log.d(TAG, "Workspace not loaded, loading now");
mModel.startLoaderForResults(
new LoaderResults(mApp, mBgDataModel, mAllAppsList, new Callbacks[0]));
- return new ArrayList<>();
+ return null;
}
- return mBgDataModel.workspaceItems;
+
+ return new WorkspaceResult(mBgDataModel.workspaceItems, mBgDataModel.appWidgets,
+ mBgDataModel.widgetsModel);
}
}
@@ -389,4 +421,17 @@
view.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
view.layout(0, 0, width, height);
}
+
+ private static class WorkspaceResult {
+ private final ArrayList<ItemInfo> mWorkspaceItems;
+ private final ArrayList<LauncherAppWidgetInfo> mAppWidgets;
+ private final WidgetsModel mWidgetsModel;
+
+ private WorkspaceResult(ArrayList<ItemInfo> workspaceItems,
+ ArrayList<LauncherAppWidgetInfo> appWidgets, WidgetsModel widgetsModel) {
+ mWorkspaceItems = workspaceItems;
+ mAppWidgets = appWidgets;
+ mWidgetsModel = widgetsModel;
+ }
+ }
}
diff --git a/src/com/android/launcher3/logging/FileLog.java b/src/com/android/launcher3/logging/FileLog.java
index 2c972a0..67f07b1 100644
--- a/src/com/android/launcher3/logging/FileLog.java
+++ b/src/com/android/launcher3/logging/FileLog.java
@@ -42,7 +42,7 @@
private static Handler sHandler = null;
private static File sLogsDirectory = null;
- private static final int LOG_DAYS = 2;
+ public static final int LOG_DAYS = 4;
public static void setDir(File logsDir) {
if (ENABLED) {
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 8289da9..199d13f 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -69,8 +69,7 @@
public class UserEventDispatcher implements ResourceBasedOverride {
private static final String TAG = "UserEvent";
- private static final boolean IS_VERBOSE =
- FeatureFlags.IS_DOGFOOD_BUILD && Utilities.isPropertyEnabled(LogConfig.USEREVENT);
+ private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.USEREVENT);
private static final String UUID_STORAGE = "uuid";
public static UserEventDispatcher newInstance(Context context,
@@ -372,6 +371,25 @@
dispatchUserEvent(event, null);
}
+ /**
+ * Logs proto lite version of LauncherEvent object to clearcut.
+ */
+ public void logLauncherEvent(
+ com.android.launcher3.userevent.LauncherLogProto.LauncherEvent launcherEvent) {
+
+ if (mPreviousHomeGesture) {
+ mPreviousHomeGesture = false;
+ }
+ mAppOrTaskLaunch = false;
+ launcherEvent.toBuilder()
+ .setElapsedContainerMillis(SystemClock.uptimeMillis() - mElapsedContainerMillis)
+ .setElapsedSessionMillis(SystemClock.uptimeMillis() - mElapsedSessionMillis).build();
+ if (!IS_VERBOSE) {
+ return;
+ }
+ Log.d(TAG, launcherEvent.toString());
+ }
+
public void logDeepShortcutsOpen(View icon) {
LogContainerProvider provider = StatsLogUtils.getLaunchProviderRecursive(icon);
if (icon == null || !(icon.getTag() instanceof ItemInfo || provider == null)) {
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index c24b939..32fce0b 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -273,7 +273,7 @@
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
folders.remove(item.id);
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
for (ItemInfo info : itemsIdMap) {
if (info.container == item.id) {
// We are deleting a folder which still contains items that
diff --git a/src/com/android/launcher3/model/GridBackupTable.java b/src/com/android/launcher3/model/GridBackupTable.java
index eb99af5..07a7551 100644
--- a/src/com/android/launcher3/model/GridBackupTable.java
+++ b/src/com/android/launcher3/model/GridBackupTable.java
@@ -33,8 +33,6 @@
import com.android.launcher3.LauncherSettings.Settings;
import com.android.launcher3.pm.UserCache;
-import java.util.Objects;
-
/**
* Helper class to backup and restore Favorites table into a separate table
* within the same data base.
@@ -63,8 +61,7 @@
private static final int STATE_SANITIZED = 2;
private final Context mContext;
- private final SQLiteDatabase mFavoritesDb;
- private final SQLiteDatabase mBackupDb;
+ private final SQLiteDatabase mDb;
private final int mOldHotseatSize;
private final int mOldGridX;
@@ -77,11 +74,10 @@
@IntDef({STATE_NOT_FOUND, STATE_RAW, STATE_SANITIZED})
private @interface BackupState { }
- public GridBackupTable(Context context, SQLiteDatabase favoritesDb, SQLiteDatabase backupDb,
- int hotseatSize, int gridX, int gridY) {
+ public GridBackupTable(Context context, SQLiteDatabase db, int hotseatSize, int gridX,
+ int gridY) {
mContext = context;
- mFavoritesDb = favoritesDb;
- mBackupDb = backupDb;
+ mDb = db;
mOldHotseatSize = hotseatSize;
mOldGridX = gridX;
@@ -94,7 +90,7 @@
*/
public boolean backupOrRestoreAsNeeded() {
// Check if backup table exists
- if (!tableExists(mBackupDb, BACKUP_TABLE_NAME)) {
+ if (!tableExists(mDb, BACKUP_TABLE_NAME)) {
if (Settings.call(mContext.getContentResolver(), Settings.METHOD_WAS_EMPTY_DB_CREATED)
.getBoolean(Settings.EXTRA_VALUE, false)) {
// No need to copy if empty DB was created.
@@ -109,7 +105,7 @@
}
long userSerial = UserCache.INSTANCE.get(mContext).getSerialNumberForUser(
Process.myUserHandle());
- copyTable(mBackupDb, BACKUP_TABLE_NAME, mFavoritesDb, Favorites.TABLE_NAME, userSerial);
+ copyTable(mDb, BACKUP_TABLE_NAME, Favorites.TABLE_NAME, userSerial);
Log.d(TAG, "Backup table found");
return true;
}
@@ -122,37 +118,28 @@
/**
* Copy valid grid entries from one table to another.
*/
- private static void copyTable(SQLiteDatabase fromDb, String fromTable, SQLiteDatabase toDb,
- String toTable, long userSerial) {
- dropTable(toDb, toTable);
- Favorites.addTableToDb(toDb, userSerial, false, toTable);
- if (fromDb != toDb) {
- toDb.execSQL("ATTACH DATABASE '" + fromDb.getPath() + "' AS from_db");
- toDb.execSQL(
- "INSERT INTO " + toTable + " SELECT * FROM from_db." + fromTable
- + " where _id > " + ID_PROPERTY);
- } else {
- toDb.execSQL("INSERT INTO " + toTable + " SELECT * FROM " + fromTable + " where _id > "
- + ID_PROPERTY);
- }
+ private static void copyTable(SQLiteDatabase db, String from, String to, long userSerial) {
+ dropTable(db, to);
+ Favorites.addTableToDb(db, userSerial, false, to);
+ db.execSQL("INSERT INTO " + to + " SELECT * FROM " + from + " where _id > " + ID_PROPERTY);
}
private void encodeDBProperties(int options) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, ID_PROPERTY);
- values.put(KEY_DB_VERSION, mFavoritesDb.getVersion());
+ values.put(KEY_DB_VERSION, mDb.getVersion());
values.put(KEY_GRID_X_SIZE, mOldGridX);
values.put(KEY_GRID_Y_SIZE, mOldGridY);
values.put(KEY_HOTSEAT_SIZE, mOldHotseatSize);
values.put(Favorites.OPTIONS, options);
- mBackupDb.insert(BACKUP_TABLE_NAME, null, values);
+ mDb.insert(BACKUP_TABLE_NAME, null, values);
}
/**
* Load DB properties from grid backup table.
*/
public @BackupState int loadDBProperties() {
- try (Cursor c = mBackupDb.query(BACKUP_TABLE_NAME, new String[] {
+ try (Cursor c = mDb.query(BACKUP_TABLE_NAME, new String[] {
KEY_DB_VERSION, // 0
KEY_GRID_X_SIZE, // 1
KEY_GRID_Y_SIZE, // 2
@@ -163,7 +150,7 @@
Log.e(TAG, "Meta data not found in backup table");
return STATE_NOT_FOUND;
}
- if (!validateDBVersion(mBackupDb.getVersion(), c.getInt(0))) {
+ if (!validateDBVersion(mDb.getVersion(), c.getInt(0))) {
return STATE_NOT_FOUND;
}
@@ -179,7 +166,7 @@
* Restore workspace from raw backup if available.
*/
public boolean restoreFromRawBackupIfAvailable(long oldProfileId) {
- if (!tableExists(mBackupDb, Favorites.BACKUP_TABLE_NAME)
+ if (!tableExists(mDb, Favorites.BACKUP_TABLE_NAME)
|| loadDBProperties() != STATE_RAW
|| mOldHotseatSize != mRestoredHotseatSize
|| mOldGridX != mRestoredGridX
@@ -187,8 +174,7 @@
// skip restore if dimensions in backup table differs from current setup.
return false;
}
- copyTable(mBackupDb, Favorites.BACKUP_TABLE_NAME, mFavoritesDb, Favorites.TABLE_NAME,
- oldProfileId);
+ copyTable(mDb, Favorites.BACKUP_TABLE_NAME, Favorites.TABLE_NAME, oldProfileId);
Log.d(TAG, "Backup restored");
return true;
}
@@ -197,8 +183,7 @@
* Performs a backup on the workspace layout.
*/
public void doBackup(long profileId, int options) {
- copyTable(mFavoritesDb, Favorites.TABLE_NAME, mBackupDb, Favorites.BACKUP_TABLE_NAME,
- profileId);
+ copyTable(mDb, Favorites.TABLE_NAME, Favorites.BACKUP_TABLE_NAME, profileId);
encodeDBProperties(options);
}
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
index 4f92066..c35c4b9 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTask.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -909,7 +909,7 @@
boolean dbChanged = false;
GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb(),
- transaction.getDb(), srcHotseatCount, sourceSize.x, sourceSize.y);
+ srcHotseatCount, sourceSize.x, sourceSize.y);
if (backupTable.backupOrRestoreAsNeeded()) {
dbChanged = true;
srcHotseatCount = backupTable.getRestoreHotseatAndGridSize(sourceSize);
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 4f61a2a..6223a23 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -59,6 +59,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderGridOrganizer;
+import com.android.launcher3.folder.FolderNameInfo;
import com.android.launcher3.folder.FolderNameProvider;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
import com.android.launcher3.icons.ComponentWithLabelAndIcon.ComponentWithIconCachingLogic;
@@ -900,15 +901,18 @@
}
private void loadFolderNames() {
- FolderNameProvider provider = FolderNameProvider.newInstance(mApp.getContext());
+ FolderNameProvider provider = FolderNameProvider.newInstance(mApp.getContext(),
+ mBgAllAppsList.data, mBgDataModel.folders);
synchronized (mBgDataModel) {
for (int i = 0; i < mBgDataModel.folders.size(); i++) {
- String[] suggestedOut = new String[FolderNameProvider.SUGGEST_MAX];
+ FolderNameInfo[] suggestionInfos =
+ new FolderNameInfo[FolderNameProvider.SUGGEST_MAX];
FolderInfo info = mBgDataModel.folders.valueAt(i);
if (info.suggestedFolderNames == null) {
- provider.getSuggestedFolderName(mApp.getContext(), info.contents, suggestedOut);
- info.suggestedFolderNames = new Intent().putExtra("suggest", suggestedOut);
+ provider.getSuggestedFolderName(mApp.getContext(), info.contents,
+ suggestionInfos);
+ info.suggestedFolderNames = new Intent().putExtra("suggest", suggestionInfos);
}
}
}
diff --git a/src/com/android/launcher3/model/ModelUtils.java b/src/com/android/launcher3/model/ModelUtils.java
index 628dd95..1473124 100644
--- a/src/com/android/launcher3/model/ModelUtils.java
+++ b/src/com/android/launcher3/model/ModelUtils.java
@@ -97,7 +97,7 @@
return Integer.compare(lhs.screenId, rhs.screenId);
}
default:
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
throw new RuntimeException(
"Unexpected container type when sorting workspace items.");
}
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index ccd1554..27fa580 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -115,8 +115,9 @@
ItemInfo modelItem = mBgDataModel.itemsIdMap.get(itemId);
if (modelItem != null && item != modelItem) {
// check all the data is consistent
- if (!Utilities.IS_DEBUG_DEVICE && !FeatureFlags.IS_DOGFOOD_BUILD &&
- modelItem instanceof WorkspaceItemInfo && item instanceof WorkspaceItemInfo) {
+ if (!Utilities.IS_DEBUG_DEVICE && !FeatureFlags.IS_STUDIO_BUILD
+ && modelItem instanceof WorkspaceItemInfo
+ && item instanceof WorkspaceItemInfo) {
if (modelItem.title.toString().equals(item.title.toString()) &&
modelItem.getIntent().filterEquals(item.getIntent()) &&
modelItem.id == item.id &&
@@ -320,7 +321,7 @@
*/
public void prepareToUndoDelete() {
if (!mPreparingToUndo) {
- if (!mDeleteRunnables.isEmpty() && FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (!mDeleteRunnables.isEmpty() && FeatureFlags.IS_STUDIO_BUILD) {
throw new IllegalStateException("There are still uncommitted delete operations!");
}
mDeleteRunnables.clear();
diff --git a/src/com/android/launcher3/model/PackageItemInfo.java b/src/com/android/launcher3/model/PackageItemInfo.java
index 3ef48cd..2fc064c 100644
--- a/src/com/android/launcher3/model/PackageItemInfo.java
+++ b/src/com/android/launcher3/model/PackageItemInfo.java
@@ -19,6 +19,8 @@
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherSettings;
+import java.util.Objects;
+
/**
* Represents a {@link Package} in the widget tray section.
*/
@@ -48,4 +50,17 @@
public PackageItemInfo clone() {
return new PackageItemInfo(this);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PackageItemInfo that = (PackageItemInfo) o;
+ return Objects.equals(packageName, that.packageName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(packageName);
+ }
}
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 842be40..0fe3673 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -108,7 +108,7 @@
private void backupWorkspace(Context context, SQLiteDatabase db) throws Exception {
InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
// TODO(pinyaoting): Support backing up workspace with multiple grid options.
- new GridBackupTable(context, db, db, idp.numHotseatIcons, idp.numColumns, idp.numRows)
+ new GridBackupTable(context, db, idp.numHotseatIcons, idp.numColumns, idp.numRows)
.doBackup(getDefaultProfileId(db), GridBackupTable.OPTION_REQUIRES_SANITIZATION);
}
@@ -117,8 +117,8 @@
throws Exception {
// TODO(pinyaoting): Support restoring workspace with multiple grid options.
final InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
- GridBackupTable backupTable = new GridBackupTable(context, db, db,
- idp.numHotseatIcons, idp.numColumns, idp.numRows);
+ GridBackupTable backupTable = new GridBackupTable(context, db, idp.numHotseatIcons,
+ idp.numColumns, idp.numRows);
if (backupTable.restoreFromRawBackupIfAvailable(getDefaultProfileId(db))) {
sanitizeDB(helper, db, backupManager);
LauncherAppState.getInstance(context).getModel().forceReload();
diff --git a/src/com/android/launcher3/util/IOUtils.java b/src/com/android/launcher3/util/IOUtils.java
index 4a4a5ca..fcb96d7 100644
--- a/src/com/android/launcher3/util/IOUtils.java
+++ b/src/com/android/launcher3/util/IOUtils.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.util.Log;
-import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import java.io.ByteArrayOutputStream;
@@ -67,7 +66,7 @@
* Utility method to debug binary data
*/
public static String createTempFile(Context context, byte[] data) {
- if (!FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (!FeatureFlags.IS_STUDIO_BUILD) {
throw new IllegalStateException("Method only allowed in development mode");
}
@@ -87,7 +86,7 @@
try {
c.close();
} catch (IOException e) {
- if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ if (FeatureFlags.IS_STUDIO_BUILD) {
Log.d(TAG, "Error closing", e);
}
}
diff --git a/src/com/android/launcher3/util/Preconditions.java b/src/com/android/launcher3/util/Preconditions.java
index ed66422..63d56e4 100644
--- a/src/com/android/launcher3/util/Preconditions.java
+++ b/src/com/android/launcher3/util/Preconditions.java
@@ -28,25 +28,25 @@
public class Preconditions {
public static void assertNotNull(Object o) {
- if (FeatureFlags.IS_DOGFOOD_BUILD && o == null) {
+ if (FeatureFlags.IS_STUDIO_BUILD && o == null) {
throw new IllegalStateException();
}
}
public static void assertWorkerThread() {
- if (FeatureFlags.IS_DOGFOOD_BUILD && !isSameLooper(MODEL_EXECUTOR.getLooper())) {
+ if (FeatureFlags.IS_STUDIO_BUILD && !isSameLooper(MODEL_EXECUTOR.getLooper())) {
throw new IllegalStateException();
}
}
public static void assertUIThread() {
- if (FeatureFlags.IS_DOGFOOD_BUILD && !isSameLooper(Looper.getMainLooper())) {
+ if (FeatureFlags.IS_STUDIO_BUILD && !isSameLooper(Looper.getMainLooper())) {
throw new IllegalStateException();
}
}
public static void assertNonUiThread() {
- if (FeatureFlags.IS_DOGFOOD_BUILD && isSameLooper(Looper.getMainLooper())) {
+ if (FeatureFlags.IS_STUDIO_BUILD && isSameLooper(Looper.getMainLooper())) {
throw new IllegalStateException();
}
}
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 9334c46..bdba39c 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.views;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import android.animation.Animator;
@@ -62,6 +64,7 @@
protected final ObjectAnimator mOpenCloseAnimator;
protected View mContent;
+ private final View mColorScrim;
protected Interpolator mScrollInterpolator;
// range [0, 1], 0=> completely open, 1=> completely closed
@@ -85,11 +88,30 @@
announceAccessibilityChanges();
}
});
+ int scrimColor = getScrimColor(mLauncher);
+ mColorScrim = scrimColor != -1 ? createColorScrim(mLauncher, scrimColor) : null;
+ }
+
+ protected void attachToContainer() {
+ if (mColorScrim != null) {
+ getPopupContainer().addView(mColorScrim);
+ }
+ getPopupContainer().addView(this);
+ }
+
+ /**
+ * Returns a scrim color for a sliding view. if returned value is -1, no scrim is added.
+ */
+ protected int getScrimColor(Context context) {
+ return -1;
}
protected void setTranslationShift(float translationShift) {
mTranslationShift = translationShift;
mContent.setTranslationY(mTranslationShift * mContent.getHeight());
+ if (mColorScrim != null) {
+ mColorScrim.setAlpha(1 - mTranslationShift);
+ }
}
@Override
@@ -127,7 +149,8 @@
/* SingleAxisSwipeDetector.Listener */
@Override
- public void onDragStart(boolean start) { }
+ public void onDragStart(boolean start) {
+ }
@Override
public boolean onDrag(float displacement) {
@@ -185,9 +208,25 @@
protected void onCloseComplete() {
mIsOpen = false;
getPopupContainer().removeView(this);
+ if (mColorScrim != null) {
+ getPopupContainer().removeView(mColorScrim);
+ }
}
protected BaseDragLayer getPopupContainer() {
return mLauncher.getDragLayer();
}
+
+
+ protected static View createColorScrim(Context context, int bgColor) {
+ View view = new View(context);
+ view.forceHasOverlappingRendering(false);
+ view.setBackgroundColor(bgColor);
+
+ BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(MATCH_PARENT, MATCH_PARENT);
+ lp.ignoreInsets = true;
+ view.setLayoutParams(lp);
+
+ return view;
+ }
}
diff --git a/src/com/android/launcher3/views/WorkEduView.java b/src/com/android/launcher3/views/WorkEduView.java
index b6c81ae..81f8327 100644
--- a/src/com/android/launcher3/views/WorkEduView.java
+++ b/src/com/android/launcher3/views/WorkEduView.java
@@ -52,11 +52,15 @@
private static final int WORK_EDU_PERSONAL_APPS = 1;
private static final int WORK_EDU_WORK_APPS = 2;
+ protected static final int FINAL_SCRIM_BG_COLOR = 0x88000000;
+
+
private Rect mInsets = new Rect();
private View mViewWrapper;
private Button mProceedButton;
private TextView mContentText;
private AllAppsPagedView mAllAppsPagedView;
+
private int mNextWorkEduStep = WORK_EDU_PERSONAL_APPS;
@@ -141,10 +145,15 @@
}
private void show() {
- mLauncher.getDragLayer().addView(this);
+ attachToContainer();
animateOpen();
}
+ @Override
+ protected int getScrimColor(Context context) {
+ return FINAL_SCRIM_BG_COLOR;
+ }
+
private void goToFirstPage() {
if (mAllAppsPagedView != null) {
mAllAppsPagedView.snapToPageImmediately(AllAppsContainerView.AdapterHolder.MAIN);
diff --git a/src/com/android/launcher3/views/WorkFooterContainer.java b/src/com/android/launcher3/views/WorkFooterContainer.java
index f8add9a..9ac8230 100644
--- a/src/com/android/launcher3/views/WorkFooterContainer.java
+++ b/src/com/android/launcher3/views/WorkFooterContainer.java
@@ -119,6 +119,13 @@
mWorkModeSwitch.refresh();
}
+ /**
+ * Returns work mode switch
+ */
+ public WorkModeSwitch getWorkModeSwitch() {
+ return mWorkModeSwitch;
+ }
+
private boolean shouldShowWorkFooter() {
Launcher launcher = Launcher.getLauncher(getContext());
return Utilities.ATLEAST_P && (hasShortcutsPermission(launcher)
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 6cae43d..df1a469 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.widget;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
@@ -42,7 +40,6 @@
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.AbstractSlideInView;
-import com.android.launcher3.views.BaseDragLayer;
/**
* Base class for various widgets popup
@@ -55,11 +52,14 @@
/* Touch handling related member variables. */
private Toast mWidgetInstructionToast;
- protected final View mColorScrim;
-
public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mColorScrim = createColorScrim(context);
+ }
+
+ protected int getScrimColor(Context context) {
+ WallpaperColorInfo colors = WallpaperColorInfo.INSTANCE.get(context);
+ int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha);
+ return setColorAlphaBound(colors.getSecondaryColor(), alpha);
}
@Override
@@ -98,16 +98,6 @@
return true;
}
- protected void attachToContainer() {
- getPopupContainer().addView(mColorScrim);
- getPopupContainer().addView(this);
- }
-
- protected void setTranslationShift(float translationShift) {
- super.setTranslationShift(translationShift);
- mColorScrim.setAlpha(1 - mTranslationShift);
- }
-
private boolean beginDraggingWidget(WidgetCell v) {
// Get the widget preview as the drag representation
WidgetImageView image = v.getWidgetView();
@@ -138,7 +128,6 @@
protected void onCloseComplete() {
super.onCloseComplete();
- getPopupContainer().removeView(mColorScrim);
clearNavBarColor();
}
@@ -177,19 +166,4 @@
protected SystemUiController getSystemUiController() {
return mLauncher.getSystemUiController();
}
-
- private static View createColorScrim(Context context) {
- View view = new View(context);
- view.forceHasOverlappingRendering(false);
-
- WallpaperColorInfo colors = WallpaperColorInfo.INSTANCE.get(context);
- int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha);
- view.setBackgroundColor(setColorAlphaBound(colors.getSecondaryColor(), alpha));
-
- BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(MATCH_PARENT, MATCH_PARENT);
- lp.ignoreInsets = true;
- view.setLayoutParams(lp);
-
- return view;
- }
}
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 5ebf8d3..ae32692 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -6,6 +6,7 @@
import static com.android.launcher3.pm.ShortcutConfigActivityInfo.queryList;
import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Process;
@@ -115,7 +116,7 @@
}
setWidgetsAndShortcuts(widgetsAndShortcuts, app, packageUser);
} catch (Exception e) {
- if (!FeatureFlags.IS_DOGFOOD_BUILD && Utilities.isBinderSizeError(e)) {
+ if (!FeatureFlags.IS_STUDIO_BUILD && Utilities.isBinderSizeError(e)) {
// the returned value may be incomplete and will not be refreshed until the next
// time Launcher starts.
// TODO: after figuring out a repro step, introduce a dirty bit to check when
@@ -243,4 +244,16 @@
}
}
}
+
+ public WidgetItem getWidgetProviderInfoByProviderName(
+ ComponentName providerName) {
+ ArrayList<WidgetItem> widgetsList = mWidgetsList.get(
+ new PackageItemInfo(providerName.getPackageName()));
+ for (WidgetItem item : widgetsList) {
+ if (item.componentName.equals(providerName)) {
+ return item;
+ }
+ }
+ return null;
+ }
}
\ No newline at end of file
diff --git a/tests/Android.mk b/tests/Android.mk
index d1a6c06..a9fff8e 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -51,7 +51,7 @@
androidx.test.rules \
androidx.test.uiautomator_uiautomator \
mockito-target-minus-junit4 \
- launcher-log-protos-lite
+ launcher_log_protos_lite
ifneq (,$(wildcard frameworks/base))
LOCAL_PRIVATE_PLATFORM_APIS := true
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index d9edc35..810c91a 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -16,17 +16,32 @@
package com.android.launcher3.ui;
import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.UNBUNDLED_POSTSUBMIT;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
+
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsPagedView;
+import com.android.launcher3.util.rule.TestStabilityRule;
+import com.android.launcher3.views.WorkFooterContainer;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.List;
+import java.util.Objects;
+
@LargeTest
@RunWith(AndroidJUnit4.class)
public class WorkTabTest extends AbstractLauncherUiTest {
@@ -52,16 +67,49 @@
}
@Test
+ // b/143285809 Remove @Stability on 02/21/20 if the test doesn't flake.
+ @TestStabilityRule.Stability(flavors = LOCAL | UNBUNDLED_POSTSUBMIT)
public void workTabExists() {
mDevice.pressHome();
- waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null);
+ waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
-
- /*
- assertTrue("Personal tab is missing", waitForLauncherCondition(
- launcher -> launcher.getAppsView().isPersonalTabVisible()));
- assertTrue("Work tab is missing", waitForLauncherCondition(
- launcher -> launcher.getAppsView().isWorkTabVisible()));
- */
+ waitForLauncherCondition("Personal tab is missing",
+ launcher -> launcher.getAppsView().isPersonalTabVisible(), 60000);
+ waitForLauncherCondition("Work tab is missing",
+ launcher -> launcher.getAppsView().isWorkTabVisible(), 60000);
}
+
+ @Test
+ // b/143285809 Remove @Stability on 02/21/20 if the test doesn't flake.
+ @TestStabilityRule.Stability(flavors = LOCAL | UNBUNDLED_POSTSUBMIT)
+ public void toggleWorks() {
+ mDevice.pressHome();
+ waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
+ executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS));
+ waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS);
+ getOnceNotNull("Apps view did not bind",
+ launcher -> launcher.getAppsView().getWorkFooterContainer());
+
+ UserManager userManager = getFromLauncher(l -> l.getSystemService(UserManager.class));
+ assertEquals(2, userManager.getUserProfiles().size());
+ UserHandle workProfile = getFromLauncher(l -> {
+ UserHandle myHandle = Process.myUserHandle();
+ List<UserHandle> userProfiles = userManager.getUserProfiles();
+ return userProfiles.get(0) == myHandle ? userProfiles.get(1) : userProfiles.get(0);
+ });
+
+ waitForLauncherCondition("work profile can't be turned off",
+ l -> userManager.requestQuietModeEnabled(true, workProfile));
+
+ assertTrue(userManager.isQuietModeEnabled(workProfile));
+ executeOnLauncher(launcher -> {
+ WorkFooterContainer wf = launcher.getAppsView().getWorkFooterContainer();
+ ((AllAppsPagedView) launcher.getAppsView().getContentView()).snapToPageImmediately(
+ AllAppsContainerView.AdapterHolder.WORK);
+ wf.getWorkModeSwitch().toggle();
+ });
+ waitForLauncherCondition("Work toggle did not work",
+ l -> l.getSystemService(UserManager.class).isQuietModeEnabled(workProfile));
+ }
+
}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
index 4b867a7..cdda0f0 100644
--- a/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
+++ b/tests/src/com/android/launcher3/util/rule/FailureWatcher.java
@@ -8,7 +8,6 @@
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -16,7 +15,6 @@
public class FailureWatcher extends TestWatcher {
private static final String TAG = "FailureWatcher";
- private static boolean sHadFailedTestDeinitialization;
final private UiDevice mDevice;
public FailureWatcher(UiDevice device) {
@@ -62,35 +60,4 @@
device.takeScreenshot(new File(pathname));
}
-
- @Override
- public Statement apply(Statement base, Description description) {
- return new Statement() {
-
- @Override
- public void evaluate() throws Throwable {
- if (sHadFailedTestDeinitialization) {
- Log.d(TAG, "Skipping due to a recent test deinitialization failure: " +
- description.getDisplayName());
- return;
- }
-
- try {
- FailureWatcher.super.apply(base, description).evaluate();
- } catch (Throwable e) {
- final String stackTrace = Log.getStackTraceString(e);
- if (!stackTrace.contains(
- "androidx.test.internal.runner.junit4.statement.RunBefores.evaluate")) {
- // Test failed to deinitialize. Since the global state is probably
- // corrupted, won't execute other tests.
- Log.d(TAG,
- "Detected an exception from test finalizer, will skip further "
- + "tests: " + stackTrace);
- sHadFailedTestDeinitialization = true;
- }
- throw e;
- }
- }
- };
- }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index abd0f24..c5fbd7c 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1251,13 +1251,14 @@
private Map<String, List<String>> getEvents() {
final Map<String, List<String>> events = new HashMap<>();
try {
- // Logcat may skip events after the specified time. Querying for events starting 1 sec
+ // Logcat may skip events after the specified time. Querying for events starting 1 min
// earlier.
- final Date startTime = new Date(mStartRecordingTime.getTime() - 10000);
- final String logcatEvents = mDevice.executeShellCommand(
- "logcat -d -v year --pid=" + getPid() + " -t "
- + DATE_TIME_FORMAT.format(startTime).replaceAll(" ", "")
- + " -s " + TestProtocol.TAPL_EVENTS_TAG);
+ final Date startTime = new Date(mStartRecordingTime.getTime() - 60000);
+ final String logcatCommand = "logcat -d -v year --pid=" + getPid() + " -t "
+ + DATE_TIME_FORMAT.format(startTime).replaceAll(" ", "")
+ + " -s " + TestProtocol.TAPL_EVENTS_TAG;
+ log("Events query command: " + logcatCommand);
+ final String logcatEvents = mDevice.executeShellCommand(logcatCommand);
final Matcher matcher = EVENT_LOG_ENTRY.matcher(logcatEvents);
while (matcher.find()) {
// Skip events before recording start time.