Merge "Not using Contacts app" into ub-launcher3-qt-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
index bd78573..0b8c1c5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.appprediction;
-import static com.android.launcher3.appprediction.PredictionUiStateManager.KEY_APP_SUGGESTION;
+import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
import android.annotation.TargetApi;
import android.app.prediction.AppPredictionContext;
@@ -26,8 +26,6 @@
import android.app.prediction.AppTargetId;
import android.content.ComponentName;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
@@ -35,12 +33,10 @@
import android.util.Log;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.util.UiThreadHelper;
-import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
-
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
@@ -48,8 +44,7 @@
* Subclass of app tracker which publishes the data to the prediction engine and gets back results.
*/
@TargetApi(Build.VERSION_CODES.Q)
-public class PredictionAppTracker extends AppLaunchTracker
- implements OnSharedPreferenceChangeListener {
+public class PredictionAppTracker extends AppLaunchTracker {
private static final String TAG = "PredictionAppTracker";
private static final boolean DBG = false;
@@ -62,8 +57,6 @@
private final Context mContext;
private final Handler mMessageHandler;
- private boolean mEnabled;
-
// Accessed only on worker thread
private AppPredictor mHomeAppPredictor;
private AppPredictor mRecentsOverviewPredictor;
@@ -71,24 +64,16 @@
public PredictionAppTracker(Context context) {
mContext = context;
mMessageHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleMessage);
-
- SharedPreferences prefs = Utilities.getPrefs(context);
- setEnabled(prefs.getBoolean(KEY_APP_SUGGESTION, true));
- prefs.registerOnSharedPreferenceChangeListener(this);
InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged);
+
+ mMessageHandler.sendEmptyMessage(MSG_INIT);
}
@UiThread
private void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) {
- // Reinitialize everything
- setEnabled(mEnabled);
- }
-
- @Override
- @UiThread
- public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- if (KEY_APP_SUGGESTION.equals(key)) {
- setEnabled(prefs.getBoolean(KEY_APP_SUGGESTION, true));
+ if ((changeFlags & CHANGE_FLAG_GRID) != 0) {
+ // Reinitialize everything
+ mMessageHandler.sendEmptyMessage(MSG_INIT);
}
}
@@ -137,13 +122,13 @@
return true;
}
case MSG_LAUNCH: {
- if (mEnabled && mHomeAppPredictor != null) {
+ if (mHomeAppPredictor != null) {
mHomeAppPredictor.notifyAppTargetEvent((AppTargetEvent) msg.obj);
}
return true;
}
case MSG_PREDICT: {
- if (mEnabled && mHomeAppPredictor != null) {
+ if (mHomeAppPredictor != null) {
String client = (String) msg.obj;
if (Client.HOME.id.equals(client)) {
mHomeAppPredictor.requestPredictionUpdate();
@@ -168,18 +153,6 @@
}
}
- @UiThread
- public void setEnabled(boolean isEnabled) {
- mEnabled = isEnabled;
- if (isEnabled) {
- mMessageHandler.removeMessages(MSG_DESTROY);
- mMessageHandler.sendEmptyMessage(MSG_INIT);
- } else {
- mMessageHandler.removeMessages(MSG_INIT);
- mMessageHandler.sendEmptyMessage(MSG_DESTROY);
- }
- }
-
@Override
@UiThread
public void onStartShortcut(String packageName, String shortcutId, UserHandle user,
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index 54fd845..48a163d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -24,8 +24,7 @@
import android.app.prediction.AppTarget;
import android.content.ComponentName;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Handler;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import com.android.launcher3.AppInfo;
@@ -61,9 +60,10 @@
* that client id.
*/
public class PredictionUiStateManager implements OnGlobalLayoutListener, ItemInfoUpdateReceiver,
- OnSharedPreferenceChangeListener, OnIDPChangeListener, OnUpdateListener {
+ OnIDPChangeListener, OnUpdateListener {
- public static final String KEY_APP_SUGGESTION = "pref_show_predictions";
+ public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state";
+ private static final long INITIAL_CALLBACK_WAIT_TIMEOUT_MS = 5000;
// TODO (b/129421797): Update the client constants
public enum Client {
@@ -81,7 +81,6 @@
new MainThreadInitializedObject<>(PredictionUiStateManager::new);
private final Context mContext;
- private final SharedPreferences mMainPrefs;
private final DynamicItemCache mDynamicItemCache;
private final List[] mPredictionServicePredictions;
@@ -94,9 +93,10 @@
private PredictionState mPendingState;
private PredictionState mCurrentState;
+ private boolean mGettingValidPredictionResults;
+
private PredictionUiStateManager(Context context) {
mContext = context;
- mMainPrefs = Utilities.getPrefs(context);
mDynamicItemCache = new DynamicItemCache(context, this::onAppsUpdated);
@@ -110,8 +110,14 @@
for (int i = 0; i < mPredictionServicePredictions.length; i++) {
mPredictionServicePredictions[i] = Collections.emptyList();
}
- // Listens for enable/disable signal, and predictions if using AiAi is disabled.
- mMainPrefs.registerOnSharedPreferenceChangeListener(this);
+
+ mGettingValidPredictionResults = Utilities.getDevicePrefs(context)
+ .getBoolean(LAST_PREDICTION_ENABLED_STATE, true);
+ if (mGettingValidPredictionResults) {
+ new Handler().postDelayed(
+ this::updatePredictionStateAfterCallback, INITIAL_CALLBACK_WAIT_TIMEOUT_MS);
+ }
+
// Call this last
mCurrentState = parseLastState();
}
@@ -177,13 +183,6 @@
}
}
- @Override
- public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- if (KEY_APP_SUGGESTION.equals(key)) {
- dispatchOnChange(true);
- }
- }
-
private void applyState(PredictionState state) {
boolean wasEnabled = mCurrentState.isEnabled;
mCurrentState = state;
@@ -198,10 +197,24 @@
}
}
+ private void updatePredictionStateAfterCallback() {
+ boolean validResults = false;
+ for (List l : mPredictionServicePredictions) {
+ validResults |= l != null && !l.isEmpty();
+ }
+ if (validResults != mGettingValidPredictionResults) {
+ mGettingValidPredictionResults = validResults;
+ Utilities.getDevicePrefs(mContext).edit()
+ .putBoolean(LAST_PREDICTION_ENABLED_STATE, true)
+ .apply();
+ }
+ dispatchOnChange(true);
+ }
+
public AppPredictor.Callback appPredictorCallback(Client client) {
return targets -> {
mPredictionServicePredictions[client.ordinal()] = targets;
- dispatchOnChange(true);
+ updatePredictionStateAfterCallback();
};
}
@@ -217,7 +230,7 @@
private PredictionState parseLastState() {
PredictionState state = new PredictionState();
- state.isEnabled = mMainPrefs.getBoolean(KEY_APP_SUGGESTION, true);
+ state.isEnabled = mGettingValidPredictionResults;
if (!state.isEnabled) {
state.apps = Collections.EMPTY_LIST;
return 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 dfcc2b7..09a1f3b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -24,7 +24,6 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
@@ -436,9 +435,9 @@
}
private boolean isInValidSystemUiState() {
- return (mSystemUiStateFlags & SYSUI_STATE_SCREEN_PINNING) == 0
- && (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
- && (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0;
+ return (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
+ && (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
+ && !ActivityManagerWrapper.getInstance().isLockToAppActive();
}
private InputConsumer newConsumer(boolean useSharedState, MotionEvent event) {
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 ed68d87..1117855 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
@@ -51,7 +51,6 @@
import com.android.quickstep.util.TaskCornerRadius;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.system.QuickStepContract;
/**
* A task in the Recents view.
@@ -60,6 +59,7 @@
private final static ColorMatrix COLOR_MATRIX = new ColorMatrix();
private final static ColorMatrix SATURATION_COLOR_MATRIX = new ColorMatrix();
+ private final static Rect EMPTY_RECT = new Rect();
public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
new FloatProperty<TaskThumbnailView>("dimAlpha") {
@@ -83,12 +83,13 @@
private final Paint mBackgroundPaint = new Paint();
private final Paint mClearPaint = new Paint();
private final Paint mDimmingPaintAfterClearing = new Paint();
- private final float mWindowCornerRadius;
private final Matrix mMatrix = new Matrix();
private float mClipBottom = -1;
private Rect mScaledInsets = new Rect();
+ private Rect mCurrentDrawnInsets = new Rect();
+ private float mCurrentDrawnCornerRadius;
private boolean mIsRotated;
private Task mTask;
@@ -117,7 +118,7 @@
mDimmingPaintAfterClearing.setColor(Color.BLACK);
mActivity = BaseActivity.fromContext(context);
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
- mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context.getResources());
+ setCurrentDrawnInsetsAndRadius(EMPTY_RECT, mCornerRadius);
}
public void bind(Task task) {
@@ -200,25 +201,24 @@
@Override
protected void onDraw(Canvas canvas) {
- TaskView taskView = (TaskView) getParent();
- float fullscreenProgress = taskView.getFullscreenProgress();
- if (mIsRotated) {
- // Don't show insets in the wrong orientation.
- fullscreenProgress = 0;
- }
- if (fullscreenProgress > 0) {
- // Draw the insets if we're being drawn fullscreen (we do this for quick switch).
- float cornerRadius = Utilities.mapRange(fullscreenProgress, mCornerRadius,
- mWindowCornerRadius);
- drawOnCanvas(canvas,
- -mScaledInsets.left * fullscreenProgress,
- -mScaledInsets.top * fullscreenProgress,
- getMeasuredWidth() + mScaledInsets.right * fullscreenProgress,
- getMeasuredHeight() + mScaledInsets.bottom * fullscreenProgress,
- cornerRadius / taskView.getRecentsView().getScaleX());
- } else {
- drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius);
- }
+ // Draw the insets if we're being drawn fullscreen (we do this for quick switch).
+ drawOnCanvas(canvas,
+ -mCurrentDrawnInsets.left,
+ -mCurrentDrawnInsets.top,
+ getMeasuredWidth() + mCurrentDrawnInsets.right,
+ getMeasuredHeight() + mCurrentDrawnInsets.bottom,
+ mCurrentDrawnCornerRadius);
+ }
+
+ public Rect getInsetsToDrawInFullscreen() {
+ // Don't show insets in the wrong orientation.
+ return mIsRotated ? EMPTY_RECT : mScaledInsets;
+ }
+
+ public void setCurrentDrawnInsetsAndRadius(Rect insets, float radius) {
+ mCurrentDrawnInsets.set(insets);
+ mCurrentDrawnCornerRadius = radius;
+ invalidate();
}
public float getCornerRadius() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 298c562..7f32b84 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -32,6 +32,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
@@ -47,6 +48,7 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
@@ -54,7 +56,6 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.PendingAnimation;
-import com.android.launcher3.util.Themes;
import com.android.launcher3.util.ViewPool.Reusable;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskIconCache;
@@ -62,11 +63,13 @@
import com.android.quickstep.TaskSystemShortcut;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
+import com.android.quickstep.util.TaskCornerRadius;
import com.android.quickstep.views.RecentsView.PageCallbacks;
import com.android.quickstep.views.RecentsView.ScrollState;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.ActivityOptionsCompat;
+import com.android.systemui.shared.system.QuickStepContract;
import java.util.List;
import java.util.function.Consumer;
@@ -150,6 +153,8 @@
}
};
+ private final TaskOutlineProvider mOutlineProvider;
+
private Task mTask;
private TaskThumbnailView mSnapshotView;
private TaskMenuView mMenuView;
@@ -158,6 +163,9 @@
private float mCurveScale;
private float mZoomScale;
private float mFullscreenProgress;
+ private final Rect mCurrentDrawnInsets = new Rect();
+ private float mCornerRadius;
+ private float mWindowCornerRadius;
private ObjectAnimator mIconAndDimAnimator;
private float mIconScaleAnimStartProgress = 0;
@@ -199,7 +207,10 @@
fromContext(context).getStatsLogManager().logTaskLaunch(getRecentsView(),
TaskUtils.getLaunchComponentKeyForTask(getTask().key));
});
- setOutlineProvider(new TaskOutlineProvider(context, getResources()));
+ mCornerRadius = TaskCornerRadius.get(context);
+ mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context.getResources());
+ mOutlineProvider = new TaskOutlineProvider(getResources(), mCornerRadius);
+ setOutlineProvider(mOutlineProvider);
}
@Override
@@ -521,17 +532,26 @@
private static final class TaskOutlineProvider extends ViewOutlineProvider {
private final int mMarginTop;
- private final float mRadius;
+ private final Rect mInsets = new Rect();
+ private float mRadius;
- TaskOutlineProvider(Context context, Resources res) {
+ TaskOutlineProvider(Resources res, float radius) {
mMarginTop = res.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
- mRadius = Themes.getDialogCornerRadius(context);
+ mRadius = radius;
+ }
+
+ public void setCurrentDrawnInsetsAndRadius(Rect insets, float radius) {
+ mInsets.set(insets);
+ mRadius = radius;
}
@Override
public void getOutline(View view, Outline outline) {
- outline.setRoundRect(0, mMarginTop, view.getWidth(),
- view.getHeight(), mRadius);
+ outline.setRoundRect(-mInsets.left,
+ mMarginTop - mInsets.top,
+ view.getWidth() + mInsets.right,
+ view.getHeight() + mInsets.bottom,
+ mRadius);
}
}
@@ -629,11 +649,19 @@
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
setClipChildren(!isFullscreen);
setClipToPadding(!isFullscreen);
- getThumbnail().invalidate();
- }
- public float getFullscreenProgress() {
- return mFullscreenProgress;
+ TaskThumbnailView thumbnail = getThumbnail();
+ Rect insets = thumbnail.getInsetsToDrawInFullscreen();
+ mCurrentDrawnInsets.set((int) (insets.left * mFullscreenProgress),
+ (int) (insets.top * mFullscreenProgress),
+ (int) (insets.right * mFullscreenProgress),
+ (int) (insets.bottom * mFullscreenProgress));
+ float cornerRadius = Utilities.mapRange(mFullscreenProgress, mCornerRadius,
+ mWindowCornerRadius) / getRecentsView().getScaleX();
+
+ thumbnail.setCurrentDrawnInsetsAndRadius(mCurrentDrawnInsets, cornerRadius);
+ mOutlineProvider.setCurrentDrawnInsetsAndRadius(mCurrentDrawnInsets, cornerRadius);
+ invalidateOutline();
}
public boolean isRunningTask() {
diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
index 72de80b..e6dbf87 100644
--- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
+++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
@@ -17,6 +17,7 @@
package com.android.quickstep;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
@@ -25,7 +26,6 @@
import android.content.pm.LauncherActivityInfo;
import android.os.Process;
import android.view.View;
-import android.widget.ProgressBar;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
@@ -49,8 +49,7 @@
@LargeTest
@RunWith(AndroidJUnit4.class)
-public class AppPredictionsUITests extends AbstractQuickStepTest {
- private static final String TAG = "AppPredictionsUITests";
+public class AppPredictionsUITests extends AbstractQuickStepTest {
private LauncherActivityInfo mSampleApp1;
private LauncherActivityInfo mSampleApp2;
@@ -91,20 +90,15 @@
mActivityMonitor.startLauncher();
mLauncher.pressHome().switchToAllApps();
- // There has not been any update, verify that progress bar is showing
- waitForLauncherCondition("Prediction is not in loading state", launcher -> {
- ProgressBar p = findLoadingBar(launcher);
- return p != null && p.isShown();
- });
-
// Dispatch an update
sendPredictionUpdate(mSampleApp1, mSampleApp2);
+ // The first update should apply immediately.
waitForLauncherCondition("Predictions were not updated in loading state",
launcher -> getPredictedApp(launcher).size() == 2);
}
/**
- * Test tat prediction update is deferred if it is already visible
+ * Test that prediction update is deferred if it is already visible
*/
@Test
@Ignore // b/131188880
@@ -124,6 +118,19 @@
assertEquals(3, getFromLauncher(this::getPredictedApp).size());
}
+ @Test
+ public void testPredictionsDisabled() {
+ mActivityMonitor.startLauncher();
+ sendPredictionUpdate();
+ mLauncher.pressHome().switchToAllApps();
+
+ waitForLauncherCondition("Predictions were not updated in loading state",
+ launcher -> launcher.getAppsView().getFloatingHeaderView()
+ .findFixedRowByType(PredictionRowView.class).getVisibility() == View.GONE);
+ assertFalse(PredictionUiStateManager.INSTANCE.get(mTargetContext)
+ .getCurrentState().isEnabled);
+ }
+
public ArrayList<BubbleTextView> getPredictedApp(Launcher launcher) {
PredictionRowView container = launcher.getAppsView().getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class);
@@ -138,20 +145,6 @@
return predictedAppViews;
}
- private ProgressBar findLoadingBar(Launcher launcher) {
- PredictionRowView container = launcher.getAppsView().getFloatingHeaderView()
- .findFixedRowByType(PredictionRowView.class);
-
- for (int i = 0; i < container.getChildCount(); i++) {
- View view = container.getChildAt(i);
- if (view instanceof ProgressBar) {
- return (ProgressBar) view;
- }
- }
- return null;
- }
-
-
private void sendPredictionUpdate(LauncherActivityInfo... activities) {
getOnUiThread(() -> {
List<AppTarget> targets = new ArrayList<>(activities.length);