Merge "Cleaning up unused allAppsIconSize/allAppsIconTextSize variables." into ub-launcher3-master
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java b/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java
index 245561e..d2b9c5e 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BitmapInfo.java
@@ -18,32 +18,45 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
public class BitmapInfo {
public static final Bitmap LOW_RES_ICON = Bitmap.createBitmap(1, 1, Config.ALPHA_8);
+ public static final BitmapInfo LOW_RES_INFO = fromBitmap(LOW_RES_ICON, null);
- public Bitmap icon;
- public int color;
+ public final Bitmap icon;
+ public final int color;
- public void applyTo(BitmapInfo info) {
- info.icon = icon;
- info.color = color;
+ public BitmapInfo(Bitmap icon, int color) {
+ this.icon = icon;
+ this.color = color;
+ }
+
+ /**
+ * Ideally icon should not be null, except in cases when generating hardware bitmap failed
+ */
+ public final boolean isNullOrLowRes() {
+ return icon == null || icon == LOW_RES_ICON;
}
public final boolean isLowRes() {
return LOW_RES_ICON == icon;
}
- public static BitmapInfo fromBitmap(Bitmap bitmap) {
- return fromBitmap(bitmap, null);
+ public static BitmapInfo fromBitmap(@NonNull Bitmap bitmap) {
+ return of(bitmap, 0);
}
- public static BitmapInfo fromBitmap(Bitmap bitmap, ColorExtractor dominantColorExtractor) {
- BitmapInfo info = new BitmapInfo();
- info.icon = bitmap;
- info.color = dominantColorExtractor != null
+ public static BitmapInfo fromBitmap(@NonNull Bitmap bitmap,
+ @Nullable ColorExtractor dominantColorExtractor) {
+ return of(bitmap, dominantColorExtractor != null
? dominantColorExtractor.findDominantColorByHue(bitmap)
- : 0;
- return info;
+ : 0);
+ }
+
+ public static BitmapInfo of(@NonNull Bitmap bitmap, int color) {
+ return new BitmapInfo(bitmap, color);
}
}
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
index 93f0538..8bae94c 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java
@@ -71,7 +71,10 @@
// Empty class name is used for storing package default entry.
public static final String EMPTY_CLASS_NAME = ".";
- public static class CacheEntry extends BitmapInfo {
+ public static class CacheEntry {
+
+ @NonNull
+ public BitmapInfo bitmap = BitmapInfo.LOW_RES_INFO;
public CharSequence title = "";
public CharSequence contentDescription = "";
}
@@ -259,23 +262,23 @@
if (!replaceExisting) {
entry = mCache.get(key);
// We can't reuse the entry if the high-res icon is not present.
- if (entry == null || entry.icon == null || entry.isLowRes()) {
+ if (entry == null || entry.bitmap.isNullOrLowRes()) {
entry = null;
}
}
if (entry == null) {
entry = new CacheEntry();
- cachingLogic.loadIcon(mContext, object, entry);
+ entry.bitmap = cachingLogic.loadIcon(mContext, object);
}
// Icon can't be loaded from cachingLogic, which implies alternative icon was loaded
// (e.g. fallback icon, default icon). So we drop here since there's no point in caching
// an empty entry.
- if (entry.icon == null) return;
+ if (entry.bitmap.isNullOrLowRes()) return;
entry.title = cachingLogic.getLabel(object);
entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
if (cachingLogic.addToMemCache()) mCache.put(key, entry);
- ContentValues values = newContentValues(entry, entry.title.toString(),
+ ContentValues values = newContentValues(entry.bitmap, entry.title.toString(),
componentName.getPackageName(), cachingLogic.getKeywords(object, mLocaleList));
addIconToDB(values, componentName, info, userSerial);
}
@@ -300,8 +303,8 @@
return mDefaultIcons.get(user);
}
- public boolean isDefaultIcon(Bitmap icon, UserHandle user) {
- return getDefaultIcon(user).icon == icon;
+ public boolean isDefaultIcon(BitmapInfo icon, UserHandle user) {
+ return getDefaultIcon(user).icon == icon.icon;
}
/**
@@ -315,7 +318,7 @@
assertWorkerThread();
ComponentKey cacheKey = new ComponentKey(componentName, user);
CacheEntry entry = mCache.get(cacheKey);
- if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
+ if (entry == null || (entry.bitmap.isLowRes() && !useLowResIcon)) {
entry = new CacheEntry();
if (cachingLogic.addToMemCache()) {
mCache.put(cacheKey, entry);
@@ -330,7 +333,7 @@
providerFetchedOnce = true;
if (object != null) {
- cachingLogic.loadIcon(mContext, object, entry);
+ entry.bitmap = cachingLogic.loadIcon(mContext, object);
} else {
if (usePackageIcon) {
CacheEntry packageEntry = getEntryForPackageLocked(
@@ -338,15 +341,15 @@
if (packageEntry != null) {
if (DEBUG) Log.d(TAG, "using package default icon for " +
componentName.toShortString());
- packageEntry.applyTo(entry);
+ entry.bitmap = packageEntry.bitmap;
entry.title = packageEntry.title;
entry.contentDescription = packageEntry.contentDescription;
}
}
- if (entry.icon == null) {
+ if (entry.bitmap == null) {
if (DEBUG) Log.d(TAG, "using default icon for " +
componentName.toShortString());
- getDefaultIcon(user).applyTo(entry);
+ entry.bitmap = getDefaultIcon(user);
}
}
}
@@ -390,10 +393,10 @@
}
if (icon != null) {
BaseIconFactory li = getIconFactory();
- li.createIconBitmap(icon).applyTo(entry);
+ entry.bitmap = li.createIconBitmap(icon);
li.close();
}
- if (!TextUtils.isEmpty(title) && entry.icon != null) {
+ if (!TextUtils.isEmpty(title) && entry.bitmap.icon != null) {
mCache.put(cacheKey, entry);
}
}
@@ -413,7 +416,7 @@
ComponentKey cacheKey = getPackageKey(packageName, user);
CacheEntry entry = mCache.get(cacheKey);
- if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
+ if (entry == null || (entry.bitmap.isLowRes() && !useLowResIcon)) {
entry = new CacheEntry();
boolean entryUpdated = true;
@@ -438,8 +441,8 @@
entry.title = appInfo.loadLabel(mPackageManager);
entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user);
- entry.icon = useLowResIcon ? LOW_RES_ICON : iconInfo.icon;
- entry.color = iconInfo.color;
+ entry.bitmap = BitmapInfo.of(
+ useLowResIcon ? LOW_RES_ICON : iconInfo.icon, iconInfo.color);
// Add the icon in the DB here, since these do not get written during
// package updates.
@@ -472,7 +475,7 @@
Long.toString(getSerialNumberForUser(cacheKey.user))});
if (c.moveToNext()) {
// Set the alpha to be 255, so that we never have a wrong color
- entry.color = setColorAlphaBound(c.getInt(0), 255);
+ entry.bitmap = BitmapInfo.of(LOW_RES_ICON, setColorAlphaBound(c.getInt(0), 255));
entry.title = c.getString(1);
if (entry.title == null) {
entry.title = "";
@@ -482,13 +485,12 @@
entry.title, cacheKey.user);
}
- if (lowRes) {
- entry.icon = LOW_RES_ICON;
- } else {
+ if (!lowRes) {
byte[] data = c.getBlob(2);
try {
- entry.icon = BitmapFactory.decodeByteArray(data, 0, data.length,
- mDecodeOptions);
+ entry.bitmap = BitmapInfo.of(
+ BitmapFactory.decodeByteArray(data, 0, data.length, mDecodeOptions),
+ entry.bitmap.color);
} catch (Exception e) { }
}
return true;
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
index e40a9c2..ea1ca53 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java
@@ -20,6 +20,7 @@
import android.os.LocaleList;
import android.os.UserHandle;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.icons.BitmapInfo;
@@ -32,7 +33,8 @@
CharSequence getLabel(T object);
- void loadIcon(Context context, T object, BitmapInfo target);
+ @NonNull
+ BitmapInfo loadIcon(Context context, T object);
/**
* Provides a option list of keywords to associate with this object
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
index 65e69b6..06580b9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
@@ -170,7 +170,7 @@
if (!details.isEmpty()) {
WorkspaceItemInfo si = new WorkspaceItemInfo(details.get(0), mContext);
try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
- si.applyFrom(li.createShortcutIcon(details.get(0), true /* badged */, null));
+ si.bitmap = li.createShortcutIcon(details.get(0), true /* badged */, null);
} catch (Exception e) {
if (DEBUG) {
Log.e(TAG, "Error loading shortcut icon for " + shortcutKey.toString());
@@ -209,7 +209,7 @@
InstantAppItemInfo info = new InstantAppItemInfo(intent, pkgName);
IconCache iconCache = LauncherAppState.getInstance(mContext).getIconCache();
iconCache.getTitleAndIcon(info, false);
- if (info.iconBitmap == null || iconCache.isDefaultIcon(info.iconBitmap, info.user)) {
+ if (info.bitmap.icon == null || iconCache.isDefaultIcon(info.bitmap, info.user)) {
return null;
}
return info;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 43cdbdb..4e73a79 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -18,6 +18,8 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+import static com.android.quickstep.util.NavBarPosition.ROTATION_LANDSCAPE;
+import static com.android.quickstep.util.NavBarPosition.ROTATION_SEASCAPE;
import android.content.Context;
import android.content.res.Configuration;
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 c1312c5..626292e 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
@@ -35,12 +35,12 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
@@ -51,6 +51,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.quickstep.SystemUiProxy;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.views.RecentsView;
@@ -106,8 +107,7 @@
}
});
mPeekAnim.start();
- recentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
mLauncher.getDragLayer().getScrim().animateToSysuiMultiplier(isPaused ? 0 : 1,
peekDuration, 0);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 738436a..1897fb2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -43,11 +44,14 @@
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.TouchController;
+import com.android.quickstep.util.AssistantUtilities;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
/**
* Handles swiping up on the nav bar to go home from launcher, e.g. overview or all apps.
@@ -104,6 +108,10 @@
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
return true;
}
+ if (FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
+ && AssistantUtilities.isExcludedAssistantRunning()) {
+ return true;
+ }
return false;
}
@@ -194,6 +202,8 @@
AbstractFloatingView.closeAllOpenViews(mLauncher);
logStateChange(topOpenView.getLogContainerType(), logAction);
}
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
} else {
// Quickly return to the state we came from (we didn't move far).
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index a4ac1b0..912be98 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -30,6 +30,7 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.view.MotionEvent;
@@ -50,6 +51,7 @@
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
/**
* Handles quick switching to a recent task from the home screen.
@@ -94,6 +96,8 @@
super.onDragStart(start);
mStartContainerType = LauncherLogProto.ContainerType.NAVBAR;
mTaskToLaunch = mLauncher.<RecentsView>getOverviewPanel().getTaskViewAt(0);
+ ActivityManagerWrapper.getInstance()
+ .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index 2755492..4f50e33 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -15,20 +15,15 @@
*/
package com.android.quickstep;
-import static android.os.VibrationEffect.EFFECT_CLICK;
-import static android.os.VibrationEffect.createPredefined;
-
-import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import android.animation.Animator;
import android.annotation.TargetApi;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
@@ -36,11 +31,6 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.provider.Settings;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
@@ -55,9 +45,9 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.graphics.RotationMode;
+import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AppWindowAnimationHelper;
@@ -98,16 +88,12 @@
protected final Context mContext;
protected final RecentsAnimationDeviceState mDeviceState;
protected final GestureState mGestureState;
- protected final OverviewComponentObserver mOverviewComponentObserver;
protected final BaseActivityInterface<T> mActivityInterface;
- protected final RecentsModel mRecentsModel;
- protected final int mRunningTaskId;
+ protected final InputConsumerController mInputConsumer;
protected final AppWindowAnimationHelper mAppWindowAnimationHelper;
protected final TransformParams mTransformParams = new TransformParams();
- private final Vibrator mVibrator;
-
// Shift in the range of [0, 1].
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
@@ -115,7 +101,6 @@
protected final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
protected final ActivityInitListener mActivityInitListener;
- protected final InputConsumerController mInputConsumer;
protected RecentsAnimationController mRecentsAnimationController;
protected RecentsAnimationTargets mRecentsAnimationTargets;
@@ -136,40 +121,24 @@
protected int mFinishingRecentsAnimationForNewTaskId = -1;
protected BaseSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
- GestureState gestureState, OverviewComponentObserver overviewComponentObserver,
- RecentsModel recentsModel, InputConsumerController inputConsumer, int runningTaskId) {
+ GestureState gestureState, InputConsumerController inputConsumer) {
mContext = context;
mDeviceState = deviceState;
mGestureState = gestureState;
- mOverviewComponentObserver = overviewComponentObserver;
mActivityInterface = gestureState.getActivityInterface();
- mRecentsModel = recentsModel;
mActivityInitListener =
mActivityInterface.createActivityInitListener(this::onActivityInit);
- mRunningTaskId = runningTaskId;
mInputConsumer = inputConsumer;
mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
- mVibrator = context.getSystemService(Vibrator.class);
+
initTransitionEndpoints(InvariantDeviceProfile.INSTANCE.get(mContext)
.getDeviceProfile(mContext));
}
protected void performHapticFeedback() {
- if (!mVibrator.hasVibrator()) {
- return;
- }
- if (Settings.System.getInt(
- mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0) {
- return;
- }
-
- VibrationEffect effect = createPredefined(EFFECT_CLICK);
- if (effect == null) {
- return;
- }
- UI_HELPER_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
+ VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
}
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {
@@ -281,7 +250,8 @@
mRecentsAnimationTargets = targets;
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
final Rect overviewStackBounds;
- RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(mRunningTaskId);
+ RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(
+ mGestureState.getRunningTaskId());
if (targets.minimizedHomeBounds != null && runningTaskTarget != null) {
overviewStackBounds = mActivityInterface
@@ -393,7 +363,7 @@
public void initWhenReady() {
// Preload the plan
- mRecentsModel.getTasks(null);
+ RecentsModel.INSTANCE.get(mContext).getTasks(null);
mActivityInitListener.register();
}
@@ -510,8 +480,8 @@
public interface Factory {
- BaseSwipeUpHandler newHandler(GestureState gestureState, RunningTaskInfo runningTask,
- long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask);
+ BaseSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs,
+ boolean continuingLastGesture, boolean isLikelyToStartNewTask);
}
protected interface RunningWindowAnim {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
index ce533a6..19c289d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -112,11 +112,6 @@
@Override
protected boolean isLauncherInitialized() {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "isLauncherInitialized.TouchInteractionService.isInitialized=" +
- TouchInteractionService.isInitialized());
- }
return super.isLauncherInitialized() && TouchInteractionService.isInitialized();
}
}
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 97a416a..7ad3f37 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -33,7 +33,6 @@
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
-import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -57,6 +56,7 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.DiscoveryBounce;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.provider.RestoreDbTask;
@@ -74,6 +74,7 @@
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.util.AssistantUtilities;
import com.android.systemui.plugins.OverscrollPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.recents.IOverviewProxy;
@@ -83,7 +84,6 @@
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.RecentsAnimationListener;
-import com.android.systemui.shared.system.TaskInfoCompat;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -135,9 +135,6 @@
TouchInteractionService.this.initInputMonitor();
preloadOverview(true /* fromInit */);
});
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, "TIS initialized");
- }
sIsInitialized = true;
}
@@ -251,7 +248,6 @@
this::createFallbackNoButtonSwipeHandler;
private ActivityManagerWrapper mAM;
- private RecentsModel mRecentsModel;
private OverviewCommandHelper mOverviewCommandHelper;
private OverviewComponentObserver mOverviewComponentObserver;
private InputConsumerController mInputConsumer;
@@ -330,7 +326,6 @@
@UiThread
public void onUserUnlocked() {
mTaskAnimationManager = new TaskAnimationManager();
- mRecentsModel = RecentsModel.INSTANCE.get(this);
mOverviewComponentObserver = new OverviewComponentObserver(this, mDeviceState);
mOverviewCommandHelper = new OverviewCommandHelper(this, mDeviceState,
mOverviewComponentObserver);
@@ -397,10 +392,6 @@
@Override
public void onDestroy() {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, "TIS destroyed");
- }
-
PluginManagerWrapper.INSTANCE.get(getBaseContext()).removePluginListener(this);
sIsInitialized = false;
@@ -430,14 +421,18 @@
Log.e(TAG, "Unknown event " + ev);
return;
}
+ if (!mDeviceState.isUserUnlocked()) {
+ return;
+ }
Object traceToken = TraceHelper.INSTANCE.beginFlagsOverride(
TraceHelper.FLAG_ALLOW_BINDER_TRACKING);
MotionEvent event = (MotionEvent) ev;
if (event.getAction() == ACTION_DOWN) {
- GestureState newGestureState = new GestureState(
- mOverviewComponentObserver.getActivityInterface(),
+ GestureState newGestureState = new GestureState(mOverviewComponentObserver,
ActiveGestureLog.INSTANCE.generateAndSetLogId());
+ newGestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
+ () -> mAM.getRunningTask(0)));
if (mDeviceState.isInSwipeUpTouchRegion(event)) {
mConsumer.onConsumerAboutToBeSwitched();
@@ -474,8 +469,7 @@
if (canStartSystemGesture) {
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
// launched while device is locked even after exiting direct boot mode (e.g. camera).
- return createDeviceLockedInputConsumer(newGestureState,
- mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
+ return createDeviceLockedInputConsumer(newGestureState);
} else {
return mResetGestureInputConsumer;
}
@@ -518,26 +512,22 @@
private InputConsumer newBaseConsumer(GestureState previousGestureState,
GestureState gestureState, MotionEvent event) {
- RunningTaskInfo runningTaskInfo = TraceHelper.whitelistIpcs("getRunningTask.0",
- () -> mAM.getRunningTask(0));
if (mDeviceState.isKeyguardShowingOccluded()) {
// This handles apps showing over the lockscreen (e.g. camera)
- return createDeviceLockedInputConsumer(gestureState, runningTaskInfo);
+ return createDeviceLockedInputConsumer(gestureState);
}
boolean forceOverviewInputConsumer = false;
- if (isExcludedAssistant(runningTaskInfo)) {
+ if (AssistantUtilities.isExcludedAssistant(gestureState.getRunningTask())) {
// In the case where we are in the excluded assistant state, ignore it and treat the
// running activity as the task behind the assistant
-
- runningTaskInfo = TraceHelper.whitelistIpcs("getRunningTask.assistant",
- () -> mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
- if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) {
- final ComponentName homeComponent =
- mOverviewComponentObserver.getHomeIntent().getComponent();
- forceOverviewInputConsumer =
- runningTaskInfo.baseIntent.getComponent().equals(homeComponent);
- }
+ gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.assistant",
+ () -> mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT /* ignoreActivityType */)));
+ ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
+ ComponentName runningComponent =
+ gestureState.getRunningTask().baseIntent.getComponent();
+ forceOverviewInputConsumer =
+ runningComponent != null && runningComponent.equals(homeComponent);
}
if (previousGestureState.getFinishingRecentsAnimationTaskId() > 0) {
@@ -545,34 +535,28 @@
// consumer but with the next task as the running task
RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
info.id = previousGestureState.getFinishingRecentsAnimationTaskId();
- return createOtherActivityInputConsumer(previousGestureState, gestureState, event,
- info);
- } else if (runningTaskInfo == null) {
+ gestureState.updateRunningTask(info);
+ return createOtherActivityInputConsumer(previousGestureState, gestureState, event);
+ } else if (gestureState.getRunningTask() == null) {
return mResetGestureInputConsumer;
} else if (previousGestureState.isRunningAnimationToLauncher()
|| gestureState.getActivityInterface().isResumed()
|| forceOverviewInputConsumer) {
- return createOverviewInputConsumer(previousGestureState, gestureState, event);
+ return createOverviewInputConsumer(
+ previousGestureState, gestureState, event, forceOverviewInputConsumer);
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get()
&& gestureState.getActivityInterface().isInLiveTileMode()) {
- return createOverviewInputConsumer(previousGestureState, gestureState, event);
- } else if (mDeviceState.isGestureBlockedActivity(runningTaskInfo)) {
+ return createOverviewInputConsumer(
+ previousGestureState, gestureState, event, forceOverviewInputConsumer);
+ } else if (mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())) {
return mResetGestureInputConsumer;
} else {
- return createOtherActivityInputConsumer(previousGestureState, gestureState, event,
- runningTaskInfo);
+ return createOtherActivityInputConsumer(previousGestureState, gestureState, event);
}
}
- private boolean isExcludedAssistant(TaskInfo info) {
- return info != null
- && TaskInfoCompat.getActivityType(info) == ACTIVITY_TYPE_ASSISTANT
- && (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
- }
-
private InputConsumer createOtherActivityInputConsumer(GestureState previousGestureState,
- GestureState gestureState,
- MotionEvent event, RunningTaskInfo runningTaskInfo) {
+ GestureState gestureState, MotionEvent event) {
final boolean shouldDefer;
final BaseSwipeUpHandler.Factory factory;
@@ -589,34 +573,36 @@
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
- gestureState, runningTaskInfo, shouldDefer, this::onConsumerInactive,
+ gestureState, shouldDefer, this::onConsumerInactive,
mInputMonitorCompat, disableHorizontalSwipe, factory);
}
- private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState,
- RunningTaskInfo taskInfo) {
- if (mDeviceState.isFullyGesturalNavMode() && taskInfo != null) {
+ private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState) {
+ if (mDeviceState.isFullyGesturalNavMode() && gestureState.getRunningTask() != null) {
return new DeviceLockedInputConsumer(this, mDeviceState, mTaskAnimationManager,
- gestureState, mInputMonitorCompat, taskInfo.taskId);
+ gestureState, mInputMonitorCompat);
} else {
return mResetGestureInputConsumer;
}
}
public InputConsumer createOverviewInputConsumer(GestureState previousGestureState,
- GestureState gestureState, MotionEvent event) {
+ GestureState gestureState, MotionEvent event,
+ boolean forceOverviewInputConsumer) {
BaseDraggingActivity activity = gestureState.getActivityInterface().getCreatedActivity();
if (activity == null) {
return mResetGestureInputConsumer;
}
if (activity.getRootView().hasWindowFocus()
- || previousGestureState.isRunningAnimationToLauncher()) {
+ || previousGestureState.isRunningAnimationToLauncher()
+ || (FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
+ && forceOverviewInputConsumer)) {
return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
false /* startingInActivityBounds */);
} else {
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
- return new OverviewWithoutFocusInputConsumer(activity, gestureState,
+ return new OverviewWithoutFocusInputConsumer(activity, mDeviceState, gestureState,
mInputMonitorCompat, disableHorizontalSwipe);
}
}
@@ -731,19 +717,15 @@
}
private BaseSwipeUpHandler createWindowTransformSwipeHandler(GestureState gestureState,
- RunningTaskInfo runningTask, long touchTimeMs, boolean continuingLastGesture,
- boolean isLikelyToStartNewTask) {
+ long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
return new WindowTransformSwipeHandler(this, mDeviceState, mTaskAnimationManager,
- gestureState, runningTask, touchTimeMs, mOverviewComponentObserver,
- continuingLastGesture, mInputConsumer, mRecentsModel);
+ gestureState, touchTimeMs, continuingLastGesture, mInputConsumer);
}
private BaseSwipeUpHandler createFallbackNoButtonSwipeHandler(GestureState gestureState,
- RunningTaskInfo runningTask, long touchTimeMs, boolean continuingLastGesture,
- boolean isLikelyToStartNewTask) {
+ long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
return new FallbackNoButtonInputConsumer(this, mDeviceState, gestureState,
- mOverviewComponentObserver, runningTask, mRecentsModel, mInputConsumer,
- isLikelyToStartNewTask, continuingLastGesture);
+ mInputConsumer, isLikelyToStartNewTask, continuingLastGesture);
}
protected boolean shouldNotifyBackGesture() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 8e9c898..b55ec20 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -39,7 +39,6 @@
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
@@ -72,7 +71,6 @@
import com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState;
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
import com.android.quickstep.GestureState.GestureEndTarget;
-import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.AppWindowAnimationHelper.TargetAlphaProvider;
@@ -193,11 +191,9 @@
public WindowTransformSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
- RunningTaskInfo runningTaskInfo, long touchTimeMs,
- OverviewComponentObserver overviewComponentObserver, boolean continuingLastGesture,
- InputConsumerController inputConsumer, RecentsModel recentsModel) {
- super(context, deviceState, gestureState, overviewComponentObserver, recentsModel,
- inputConsumer, runningTaskInfo.id);
+ long touchTimeMs, boolean continuingLastGesture,
+ InputConsumerController inputConsumer) {
+ super(context, deviceState, gestureState, inputConsumer);
mTaskAnimationManager = taskAnimationManager;
mTouchTimeMs = touchTimeMs;
mContinuingLastGesture = continuingLastGesture;
@@ -291,9 +287,9 @@
mStateCallback.setState(STATE_LAUNCHER_PRESENT);
if (alreadyOnHome) {
- onLauncherStart(activity);
+ onLauncherStart();
} else {
- activity.setOnStartCallback(this::onLauncherStart);
+ activity.runOnceOnStart(this::onLauncherStart);
}
setupRecentsViewUi();
@@ -305,7 +301,8 @@
return mGestureState.getEndTarget() != HOME;
}
- private void onLauncherStart(final T activity) {
+ private void onLauncherStart() {
+ final T activity = mActivityInterface.getCreatedActivity();
if (mActivity != activity) {
return;
}
@@ -380,7 +377,7 @@
private void onDeferredActivityLaunch() {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
+ mActivityInterface.switchRunningTaskViewToScreenshot(
null, () -> {
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
});
@@ -394,7 +391,7 @@
updateSysUiFlags(mCurrentShift.value);
return;
}
- mRecentsView.onGestureAnimationStart(mRunningTaskId);
+ mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId());
}
private void launcherFrameDrawn() {
@@ -443,9 +440,9 @@
if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
return;
}
- RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationTargets == null
- ? null
- : mRecentsAnimationTargets.findTask(mRunningTaskId);
+ RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationTargets != null
+ ? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId())
+ : null;
final boolean recentsAttachedToAppWindow;
if (mGestureState.getEndTarget() != null) {
recentsAttachedToAppWindow = mGestureState.getEndTarget().recentsAttachedToAppWindow;
@@ -522,7 +519,7 @@
@Override
public Intent getLaunchIntent() {
- return mOverviewComponentObserver.getOverviewIntent();
+ return mGestureState.getOverviewIntent();
}
@Override
@@ -1006,7 +1003,9 @@
@Override
public void onConsumerAboutToBeSwitched() {
if (mActivity != null) {
- mActivity.setOnStartCallback(null);
+ // In the off chance that the gesture ends before Launcher is started, we should clear
+ // the callback here so that it doesn't update with the wrong state
+ mActivity.clearRunOnceOnStartCallback();
}
if (mGestureState.getEndTarget() != null && !mGestureState.isRunningAnimationToLauncher()) {
cancelCurrentAnimation();
@@ -1087,7 +1086,9 @@
mRecentsView.onGestureAnimationEnd();
// Reset the callback for deferred activity launches
- mActivityInterface.setOnDeferredActivityLaunchCallback(null);
+ if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ mActivityInterface.setOnDeferredActivityLaunchCallback(null);
+ }
mActivity.getRootView().setOnApplyWindowInsetsListener(null);
removeLiveTileOverlay();
}
@@ -1113,13 +1114,14 @@
}
private void switchToScreenshot() {
+ final int runningTaskId = mGestureState.getRunningTaskId();
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsAnimationController != null) {
// Update the screenshot of the task
if (mTaskSnapshot == null) {
- mTaskSnapshot = mRecentsAnimationController.screenshotTask(mRunningTaskId);
+ mTaskSnapshot = mRecentsAnimationController.screenshotTask(runningTaskId);
}
- mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot, false /* refreshNow */);
+ mRecentsView.updateThumbnail(runningTaskId, mTaskSnapshot, false /* refreshNow */);
}
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
} else if (!hasTargets()) {
@@ -1130,7 +1132,7 @@
if (mRecentsAnimationController != null) {
// Update the screenshot of the task
if (mTaskSnapshot == null) {
- mTaskSnapshot = mRecentsAnimationController.screenshotTask(mRunningTaskId);
+ mTaskSnapshot = mRecentsAnimationController.screenshotTask(runningTaskId);
}
final TaskView taskView;
if (mGestureState.getEndTarget() == HOME) {
@@ -1138,7 +1140,7 @@
// taken in the correct orientation, but no need to update the thumbnail.
taskView = null;
} else {
- taskView = mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot);
+ taskView = mRecentsView.updateThumbnail(runningTaskId, mTaskSnapshot);
}
if (taskView != null && !mCanceled) {
// Defer finishing the animation until the next launcher frame with the
@@ -1192,8 +1194,7 @@
}
mRecentsView.onSwipeUpAnimationSuccess();
- RecentsModel.INSTANCE.get(mContext).onOverviewShown(false, TAG);
-
+ SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG);
doLogGesture(RECENTS);
reset();
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 370f161..e448c5b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -85,7 +85,6 @@
private final AppWindowAnimationHelper.TransformParams mTransformParams;
private final Point mDisplaySize;
private final MultiStateCallback mStateCallback;
- public final int mRunningTaskId;
private VelocityTracker mVelocityTracker;
private float mProgress;
@@ -97,7 +96,7 @@
public DeviceLockedInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
- InputMonitorCompat inputMonitorCompat, int runningTaskId) {
+ InputMonitorCompat inputMonitorCompat) {
mContext = context;
mDeviceState = deviceState;
mTaskAnimationManager = taskAnimationManager;
@@ -106,7 +105,6 @@
mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
mTransformParams = new AppWindowAnimationHelper.TransformParams();
mInputMonitorCompat = inputMonitorCompat;
- mRunningTaskId = runningTaskId;
// Do not use DeviceProfile as the user data might be locked
mDisplaySize = DefaultDisplay.INSTANCE.get(context).getInfo().realSize;
@@ -221,7 +219,8 @@
mRecentsAnimationTargets = targets;
Rect displaySize = new Rect(0, 0, mDisplaySize.x, mDisplaySize.y);
- RemoteAnimationTargetCompat targetCompat = targets.findTask(mRunningTaskId);
+ RemoteAnimationTargetCompat targetCompat = targets.findTask(
+ mGestureState.getRunningTaskId());
if (targetCompat != null) {
mAppWindowAnimationHelper.updateSource(displaySize, targetCompat);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
index 7b24bd9..b6cd456 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java
@@ -27,7 +27,6 @@
import android.animation.Animator;
import android.animation.AnimatorSet;
-import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
@@ -47,11 +46,9 @@
import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.MultiStateCallback;
-import com.android.quickstep.OverviewComponentObserver;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.RecentsAnimationController;
import com.android.quickstep.RecentsAnimationDeviceState;
-import com.android.quickstep.RecentsModel;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.RecentsAnimationTargets;
@@ -108,24 +105,18 @@
private final boolean mRunningOverHome;
private final boolean mSwipeUpOverHome;
- private final RunningTaskInfo mRunningTaskInfo;
-
private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f);
private RunningWindowAnim mFinishAnimation;
public FallbackNoButtonInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
- GestureState gestureState, OverviewComponentObserver overviewComponentObserver,
- RunningTaskInfo runningTaskInfo, RecentsModel recentsModel,
- InputConsumerController inputConsumer,
+ GestureState gestureState, InputConsumerController inputConsumer,
boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
- super(context, deviceState, gestureState, overviewComponentObserver, recentsModel,
- inputConsumer, runningTaskInfo.id);
+ super(context, deviceState, gestureState, inputConsumer);
mLauncherAlpha.value = 1;
- mRunningTaskInfo = runningTaskInfo;
mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
mContinuingLastGesture = continuingLastGesture;
- mRunningOverHome = ActivityManagerWrapper.isHomeTask(runningTaskInfo);
+ mRunningOverHome = ActivityManagerWrapper.isHomeTask(mGestureState.getRunningTask());
mSwipeUpOverHome = mRunningOverHome && !mInQuickSwitchMode;
if (mSwipeUpOverHome) {
@@ -182,9 +173,9 @@
if (!mContinuingLastGesture) {
if (mRunningOverHome) {
- mRecentsView.onGestureAnimationStart(mRunningTaskInfo);
+ mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask());
} else {
- mRecentsView.onGestureAnimationStart(mRunningTaskId);
+ mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId());
}
}
mStateCallback.setStateOnUiThread(STATE_RECENTS_PRESENT);
@@ -230,9 +221,9 @@
@Override
public Intent getLaunchIntent() {
if (mInQuickSwitchMode || mSwipeUpOverHome) {
- return mOverviewComponentObserver.getOverviewIntent();
+ return mGestureState.getOverviewIntent();
} else {
- return mOverviewComponentObserver.getHomeIntent();
+ return mGestureState.getHomeIntent();
}
}
@@ -329,7 +320,7 @@
if (mSwipeUpOverHome) {
mRecentsAnimationController.finish(false, null, false);
// Send a home intent to clear the task stack
- mContext.startActivity(mOverviewComponentObserver.getHomeIntent());
+ mContext.startActivity(mGestureState.getHomeIntent());
} else {
mRecentsAnimationController.finish(true, null, true);
}
@@ -344,7 +335,8 @@
break;
}
- ThumbnailData thumbnail = mRecentsAnimationController.screenshotTask(mRunningTaskId);
+ final int runningTaskId = mGestureState.getRunningTaskId();
+ ThumbnailData thumbnail = mRecentsAnimationController.screenshotTask(runningTaskId);
mRecentsAnimationController.setDeferCancelUntilNextTransition(true /* defer */,
false /* screenshot */);
@@ -353,9 +345,9 @@
Bundle extras = new Bundle();
extras.putBinder(EXTRA_THUMBNAIL, new ObjectWrapper<>(thumbnail));
- extras.putInt(EXTRA_TASK_ID, mRunningTaskId);
+ extras.putInt(EXTRA_TASK_ID, runningTaskId);
- Intent intent = new Intent(mOverviewComponentObserver.getOverviewIntent())
+ Intent intent = new Intent(mGestureState.getOverviewIntent())
.putExtras(extras);
mContext.startActivity(intent, options.toBundle());
mRecentsAnimationController.cleanupScreenshot();
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 aeab4b5..bf2128d 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
@@ -30,7 +30,6 @@
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.annotation.TargetApi;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
@@ -58,7 +57,6 @@
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;
@@ -81,14 +79,11 @@
private final GestureState mGestureState;
private RecentsAnimationCallbacks mActiveCallbacks;
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
- private final RunningTaskInfo mRunningTask;
private final InputMonitorCompat mInputMonitorCompat;
private final BaseActivityInterface mActivityInterface;
private final BaseSwipeUpHandler.Factory mHandlerFactory;
- private final NavBarPosition mNavBarPosition;
-
private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
private final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
@@ -124,8 +119,7 @@
public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
- RunningTaskInfo runningTaskInfo, boolean isDeferredDownTarget,
- Consumer<OtherActivityInputConsumer> onCompleteCallback,
+ boolean isDeferredDownTarget, Consumer<OtherActivityInputConsumer> onCompleteCallback,
InputMonitorCompat inputMonitorCompat, boolean disableHorizontalSwipe,
Factory handlerFactory) {
super(base);
@@ -133,7 +127,6 @@
mTaskAnimationManager = taskAnimationManager;
mGestureState = gestureState;
mMainThreadHandler = new Handler(Looper.getMainLooper());
- mRunningTask = runningTaskInfo;
mHandlerFactory = handlerFactory;
mActivityInterface = mGestureState.getActivityInterface();
@@ -146,8 +139,6 @@
boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
-
- mNavBarPosition = new NavBarPosition(base);
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
float slop = QUICKSTEP_TOUCH_SLOP_RATIO * mTouchSlop;
@@ -179,7 +170,7 @@
if (mPassedWindowMoveSlop && mInteractionHandler != null
&& !mRecentsViewDispatcher.hasConsumer()) {
mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
- mNavBarPosition.getRotationMode()));
+ mDeviceState.getNavBarPosition().getRotationMode()));
}
int edgeFlags = ev.getEdgeFlags();
ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
@@ -325,7 +316,7 @@
long touchTimeMs, boolean isLikelyToStartNewTask) {
ActiveGestureLog.INSTANCE.addLog("startRecentsAnimation");
- mInteractionHandler = mHandlerFactory.newHandler(mGestureState, mRunningTask, touchTimeMs,
+ mInteractionHandler = mHandlerFactory.newHandler(mGestureState, touchTimeMs,
mTaskAnimationManager.isRecentsAnimationRunning(), isLikelyToStartNewTask);
mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished);
mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler::onMotionPauseChanged);
@@ -360,8 +351,10 @@
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
- float velocity = mNavBarPosition.isRightEdge() ? velocityX
- : mNavBarPosition.isLeftEdge() ? -velocityX
+ float velocity = mDeviceState.getNavBarPosition().isRightEdge()
+ ? velocityX
+ : mDeviceState.getNavBarPosition().isLeftEdge()
+ ? -velocityX
: velocityY;
mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
@@ -414,9 +407,9 @@
}
private float getDisplacement(MotionEvent ev) {
- if (mNavBarPosition.isRightEdge()) {
+ if (mDeviceState.getNavBarPosition().isRightEdge()) {
return ev.getX() - mDownPos.x;
- } else if (mNavBarPosition.isLeftEdge()) {
+ } else if (mDeviceState.getNavBarPosition().isLeftEdge()) {
return mDownPos.x - ev.getX();
} else {
return ev.getY() - mDownPos.y;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
index 50069ea..875ec29 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
@@ -21,9 +21,9 @@
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
-import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.content.Context;
+import android.content.Intent;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -35,36 +35,34 @@
import com.android.launcher3.logging.StatsLogUtils;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.quickstep.BaseActivityInterface;
-import com.android.quickstep.InputConsumer;
import com.android.quickstep.GestureState;
+import com.android.quickstep.InputConsumer;
+import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.util.ActiveGestureLog;
-import com.android.quickstep.util.NavBarPosition;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
public class OverviewWithoutFocusInputConsumer implements InputConsumer {
+ private final Context mContext;
+ private final RecentsAnimationDeviceState mDeviceState;
+ private final GestureState mGestureState;
private final InputMonitorCompat mInputMonitor;
private final boolean mDisableHorizontalSwipe;
private final PointF mDownPos = new PointF();
private final float mSquaredTouchSlop;
- private final Context mContext;
- private final NavBarPosition mNavBarPosition;
- private final BaseActivityInterface mActivityInterface;
private boolean mInterceptedTouch;
private VelocityTracker mVelocityTracker;
- public OverviewWithoutFocusInputConsumer(Context context, GestureState gestureState,
+ public OverviewWithoutFocusInputConsumer(Context context,
+ RecentsAnimationDeviceState deviceState, GestureState gestureState,
InputMonitorCompat inputMonitor, boolean disableHorizontalSwipe) {
+ mContext = context;
+ mDeviceState = deviceState;
+ mGestureState = gestureState;
mInputMonitor = inputMonitor;
mDisableHorizontalSwipe = disableHorizontalSwipe;
- mContext = context;
- mActivityInterface = gestureState.getActivityInterface();
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
- mNavBarPosition = new NavBarPosition(context);
-
mVelocityTracker = VelocityTracker.obtain();
}
@@ -135,8 +133,11 @@
mVelocityTracker.computeCurrentVelocity(100);
float velocityX = mVelocityTracker.getXVelocity();
float velocityY = mVelocityTracker.getYVelocity();
- float velocity = mNavBarPosition.isRightEdge()
- ? -velocityX : (mNavBarPosition.isLeftEdge() ? velocityX : -velocityY);
+ float velocity = mDeviceState.getNavBarPosition().isRightEdge()
+ ? -velocityX
+ : mDeviceState.getNavBarPosition().isLeftEdge()
+ ? velocityX
+ : -velocityY;
final boolean triggerQuickstep;
int touch = Touch.FLING;
@@ -150,9 +151,9 @@
}
if (triggerQuickstep) {
- mActivityInterface.closeOverlay();
- ActivityManagerWrapper.getInstance()
- .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
+ mContext.startActivity(new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
ActiveGestureLog.INSTANCE.addLog("startQuickstep");
BaseActivity activity = BaseDraggingActivity.fromContext(mContext);
int pageIndex = -1; // This number doesn't reflect workspace page index.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AssistantUtilities.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AssistantUtilities.java
new file mode 100644
index 0000000..552db1f
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AssistantUtilities.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
+
+import android.annotation.TargetApi;
+import android.app.TaskInfo;
+import android.content.Intent;
+import android.os.Build;
+
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskInfoCompat;
+
+/**
+ * Utility class for interacting with the Assistant.
+ */
+@TargetApi(Build.VERSION_CODES.Q)
+public final class AssistantUtilities {
+
+ /** Returns true if an Assistant activity that is excluded from recents is running. */
+ public static boolean isExcludedAssistantRunning() {
+ return isExcludedAssistant(ActivityManagerWrapper.getInstance().getRunningTask());
+ }
+
+ /** Returns true if the given task holds an Assistant activity that is excluded from recents. */
+ public static boolean isExcludedAssistant(TaskInfo info) {
+ return info != null
+ && TaskInfoCompat.getActivityType(info) == ACTIVITY_TYPE_ASSISTANT
+ && (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
+ }
+
+ private AssistantUtilities() {}
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
deleted file mode 100644
index e2524b1..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.util;
-
-import static com.android.launcher3.uioverrides.QuickstepLauncher.ROTATION_LANDSCAPE;
-import static com.android.launcher3.uioverrides.QuickstepLauncher.ROTATION_SEASCAPE;
-import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
-
-import android.content.Context;
-import android.view.Surface;
-
-import com.android.launcher3.graphics.RotationMode;
-import com.android.launcher3.util.DefaultDisplay;
-import com.android.quickstep.SysUINavigationMode;
-
-/**
- * Utility class to check nav bar position
- */
-public class NavBarPosition {
-
- private final SysUINavigationMode.Mode mMode;
- private final int mDisplayRotation;
-
- public NavBarPosition(Context context) {
- mMode = SysUINavigationMode.getMode(context);
- mDisplayRotation = DefaultDisplay.INSTANCE.get(context).getInfo().rotation;
- }
-
- public boolean isRightEdge() {
- return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
- }
-
- public boolean isLeftEdge() {
- return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
- }
-
- public RotationMode getRotationMode() {
- return isLeftEdge() ? ROTATION_SEASCAPE
- : (isRightEdge() ? ROTATION_LANDSCAPE : RotationMode.NORMAL);
- }
-}
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 5d4665d..c634825 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
@@ -1673,8 +1673,8 @@
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
final int[] visibleTasks = getVisibleChildrenRange();
- event.setFromIndex(taskViewCount - visibleTasks[1] - 1);
- event.setToIndex(taskViewCount - visibleTasks[0] - 1);
+ event.setFromIndex(taskViewCount - visibleTasks[1]);
+ event.setToIndex(taskViewCount - visibleTasks[0]);
event.setItemCount(taskViewCount);
}
}
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 0dfc39b..57327f8 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
@@ -727,8 +727,8 @@
final RecentsView recentsView = getRecentsView();
final AccessibilityNodeInfo.CollectionItemInfo itemInfo =
AccessibilityNodeInfo.CollectionItemInfo.obtain(
- 0, 1, recentsView.getChildCount() - recentsView.indexOfChild(this) - 1, 1,
- false);
+ 0, 1, recentsView.getTaskViewCount() - recentsView.indexOfChild(this) - 1,
+ 1, false);
info.setCollectionItemInfo(itemInfo);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
index 39b0f8d..3cb0088 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
@@ -14,7 +14,7 @@
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
-import com.android.quickstep.RecentsModel;
+import com.android.quickstep.SystemUiProxy;
/**
* Touch controller for handling edge swipes in landscape/seascape UI
@@ -73,7 +73,7 @@
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
super.onSwipeInteractionCompleted(targetState, logAction);
if (mStartState == NORMAL && targetState == OVERVIEW) {
- RecentsModel.INSTANCE.get(mLauncher).onOverviewShown(true, TAG);
+ SystemUiProxy.INSTANCE.get(mLauncher).onOverviewShown(true, TAG);
}
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 28bd3d7..99b2a81 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -47,7 +47,6 @@
import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.quickstep.RecentsModel;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.LayoutUtils;
@@ -300,7 +299,7 @@
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
super.onSwipeInteractionCompleted(targetState, logAction);
if (mStartState == NORMAL && targetState == OVERVIEW) {
- RecentsModel.INSTANCE.get(mLauncher).onOverviewShown(true, TAG);
+ SystemUiProxy.INSTANCE.get(mLauncher).onOverviewShown(true, TAG);
}
}
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 98ff410..ae0886b 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -17,7 +17,10 @@
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
+import android.app.ActivityManager;
+import android.content.Intent;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.systemui.shared.recents.model.ThumbnailData;
import java.util.ArrayList;
@@ -56,6 +59,8 @@
public final boolean recentsAttachedToAppWindow;
}
+ private static final String TAG = "GestureState";
+
private static final ArrayList<String> STATE_NAMES = new ArrayList<>();
private static int FLAG_COUNT = 0;
private static int getFlagForIndex(String name) {
@@ -98,25 +103,39 @@
// Needed to interact with the current activity
+ private final Intent mHomeIntent;
+ private final Intent mOverviewIntent;
private final BaseActivityInterface mActivityInterface;
private final MultiStateCallback mStateCallback;
private final int mGestureId;
+ private ActivityManager.RunningTaskInfo mRunningTask;
private GestureEndTarget mEndTarget;
// TODO: This can be removed once we stop finishing the animation when starting a new task
private int mFinishingRecentsAnimationTaskId = -1;
- public GestureState(BaseActivityInterface activityInterface, int gestureId) {
- mActivityInterface = activityInterface;
- mGestureId = gestureId;
+ public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
+ mHomeIntent = componentObserver.getHomeIntent();
+ mOverviewIntent = componentObserver.getOverviewIntent();
+ mActivityInterface = componentObserver.getActivityInterface();
mStateCallback = new MultiStateCallback(STATE_NAMES.toArray(new String[0]));
+ mGestureId = gestureId;
}
public GestureState() {
// Do nothing, only used for initializing the gesture state prior to user unlock
+ mHomeIntent = new Intent();
+ mOverviewIntent = new Intent();
mActivityInterface = null;
- mGestureId = -1;
mStateCallback = new MultiStateCallback(STATE_NAMES.toArray(new String[0]));
+ mGestureId = -1;
+ }
+
+ /**
+ * @return whether the gesture state has the provided {@param stateMask} flags set.
+ */
+ public boolean hasState(int stateMask) {
+ return mStateCallback.hasStates(stateMask);
}
/**
@@ -134,6 +153,20 @@
}
/**
+ * @return the intent for the Home component.
+ */
+ public Intent getHomeIntent() {
+ return mHomeIntent;
+ }
+
+ /**
+ * @return the intent for the Overview component.
+ */
+ public Intent getOverviewIntent() {
+ return mOverviewIntent;
+ }
+
+ /**
* @return the interface to the activity handing the UI updates for this gesture.
*/
public <T extends BaseDraggingActivity> BaseActivityInterface<T> getActivityInterface() {
@@ -148,6 +181,27 @@
}
/**
+ * @return the running task for this gesture.
+ */
+ public ActivityManager.RunningTaskInfo getRunningTask() {
+ return mRunningTask;
+ }
+
+ /**
+ * @return the running task id for this gesture.
+ */
+ public int getRunningTaskId() {
+ return mRunningTask != null ? mRunningTask.taskId : -1;
+ }
+
+ /**
+ * Updates the running task for the gesture to be the given {@param runningTask}.
+ */
+ public void updateRunningTask(ActivityManager.RunningTaskInfo runningTask) {
+ mRunningTask = runningTask;
+ }
+
+ /**
* @return the end target for this gesture (if known).
*/
public GestureEndTarget getEndTarget() {
@@ -155,14 +209,6 @@
}
/**
- * @return whether the current gesture is still running a recents animation to a state in the
- * Launcher or Recents activity.
- */
- public boolean isRunningAnimationToLauncher() {
- return isRecentsAnimationRunning() && mEndTarget != null && mEndTarget.isLauncher;
- }
-
- /**
* Sets the end target of this gesture and immediately notifies the state changes.
*/
public void setEndTarget(GestureEndTarget target) {
@@ -202,6 +248,15 @@
}
/**
+ * @return whether the current gesture is still running a recents animation to a state in the
+ * Launcher or Recents activity.
+ * Updates the running task for the gesture to be the given {@param runningTask}.
+ */
+ public boolean isRunningAnimationToLauncher() {
+ return isRecentsAnimationRunning() && mEndTarget != null && mEndTarget.isLauncher;
+ }
+
+ /**
* @return whether the recents animation is started but not yet ended
*/
public boolean isRecentsAnimationRunning() {
diff --git a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java
deleted file mode 100644
index bd6204a..0000000
--- a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import android.annotation.TargetApi;
-import android.app.ActivityManager.TaskDescription;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.os.UserHandle;
-import android.util.LruCache;
-import android.util.SparseArray;
-
-import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.graphics.DrawableFactory;
-import com.android.launcher3.icons.LauncherIcons;
-import com.android.systemui.shared.recents.model.IconLoader;
-import com.android.systemui.shared.recents.model.TaskKeyLruCache;
-
-/**
- * Extension of {@link IconLoader} with icon normalization support
- */
-@TargetApi(Build.VERSION_CODES.O)
-public class NormalizedIconLoader extends IconLoader {
-
- private final SparseArray<BitmapInfo> mDefaultIcons = new SparseArray<>();
- private final DrawableFactory mDrawableFactory;
- private final boolean mDisableColorExtraction;
-
- public NormalizedIconLoader(Context context, TaskKeyLruCache<Drawable> iconCache,
- LruCache<ComponentName, ActivityInfo> activityInfoCache,
- boolean disableColorExtraction) {
- super(context, iconCache, activityInfoCache);
- mDrawableFactory = DrawableFactory.INSTANCE.get(context);
- mDisableColorExtraction = disableColorExtraction;
- }
-
- @Override
- public Drawable getDefaultIcon(int userId) {
- synchronized (mDefaultIcons) {
- BitmapInfo info = mDefaultIcons.get(userId);
- if (info == null) {
- info = getBitmapInfo(Resources.getSystem()
- .getDrawable(android.R.drawable.sym_def_app_icon), userId, 0, false);
- mDefaultIcons.put(userId, info);
- }
-
- return new FastBitmapDrawable(info);
- }
- }
-
- @Override
- protected Drawable createBadgedDrawable(Drawable drawable, int userId, TaskDescription desc) {
- return new FastBitmapDrawable(getBitmapInfo(drawable, userId, desc.getPrimaryColor(),
- false));
- }
-
- private BitmapInfo getBitmapInfo(Drawable drawable, int userId,
- int primaryColor, boolean isInstantApp) {
- try (LauncherIcons la = LauncherIcons.obtain(mContext)) {
- if (mDisableColorExtraction) {
- la.disableColorExtraction();
- }
- la.setWrapperBackgroundColor(primaryColor);
-
- // User version code O, so that the icon is always wrapped in an adaptive icon container
- return la.createBadgedIconBitmap(drawable, UserHandle.of(userId),
- Build.VERSION_CODES.O, isInstantApp);
- }
- }
-
- @Override
- protected Drawable getBadgedActivityIcon(ActivityInfo activityInfo, int userId,
- TaskDescription desc) {
- BitmapInfo bitmapInfo = getBitmapInfo(
- activityInfo.loadUnbadgedIcon(mContext.getPackageManager()),
- userId,
- desc.getPrimaryColor(),
- activityInfo.applicationInfo.isInstantApp());
- return mDrawableFactory.newIcon(mContext, bitmapInfo, activityInfo);
- }
-}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 9d5120d..333e179 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -48,11 +48,10 @@
private final Consumer<RecentsAnimationController> mOnFinishedListener;
private final boolean mShouldMinimizeSplitScreen;
- private boolean mWindowThresholdCrossed = false;
-
private InputConsumerController mInputConsumerController;
private Supplier<InputConsumer> mInputProxySupplier;
private InputConsumer mInputConsumer;
+ private boolean mWindowThresholdCrossed = false;
private boolean mTouchInProgress;
private boolean mFinishPending;
@@ -62,8 +61,6 @@
mController = controller;
mOnFinishedListener = onFinishedListener;
mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen;
-
- setWindowThresholdCrossed(mWindowThresholdCrossed);
}
/**
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 1855e64..81f411e 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -17,8 +17,10 @@
import static android.content.Intent.ACTION_USER_UNLOCKED;
+import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
import static com.android.launcher3.ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE;
import static com.android.launcher3.ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
@@ -35,14 +37,17 @@
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Process;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.MotionEvent;
@@ -57,6 +62,7 @@
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DefaultDisplay;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
+import com.android.quickstep.util.NavBarPosition;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
@@ -72,16 +78,17 @@
NavigationModeChangeListener,
DefaultDisplay.DisplayInfoChangeListener {
- private Context mContext;
- private UserManagerCompat mUserManager;
- private SysUINavigationMode mSysUiNavMode;
- private DefaultDisplay mDefaultDisplay;
- private int mDisplayId;
+ private final Context mContext;
+ private final UserManagerCompat mUserManager;
+ private final SysUINavigationMode mSysUiNavMode;
+ private final DefaultDisplay mDefaultDisplay;
+ private final int mDisplayId;
private final ArrayList<Runnable> mOnDestroyActions = new ArrayList<>();
private @SystemUiStateFlags int mSystemUiStateFlags;
private SysUINavigationMode.Mode mMode = THREE_BUTTONS;
+ private NavBarPosition mNavBarPosition;
private final RectF mSwipeUpTouchRegion = new RectF();
private final Region mDeferredGestureRegion = new Region();
@@ -108,11 +115,13 @@
private ComponentName mGestureBlockedActivity;
public RecentsAnimationDeviceState(Context context) {
+ final ContentResolver resolver = context.getContentResolver();
mContext = context;
mUserManager = UserManagerCompat.getInstance(context);
mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
mDefaultDisplay = DefaultDisplay.INSTANCE.get(context);
mDisplayId = mDefaultDisplay.getInfo().id;
+ runOnDestroy(() -> mDefaultDisplay.removeChangeListener(this));
// Register for user unlocked if necessary
mIsUserUnlocked = mUserManager.isUserUnlocked(Process.myUserHandle());
@@ -155,7 +164,6 @@
for (Runnable r : mOnDestroyActions) {
r.run();
}
- mDefaultDisplay.removeChangeListener(this);
}
/**
@@ -183,6 +191,7 @@
mExclusionListener.unregister();
}
mMode = newMode;
+ mNavBarPosition = new NavBarPosition(mMode, mDefaultDisplay.getInfo());
}
@Override
@@ -191,6 +200,7 @@
return;
}
+ mNavBarPosition = new NavBarPosition(mMode, info);
updateGestureTouchRegions();
}
@@ -202,6 +212,13 @@
}
/**
+ * @return the nav bar position for the current nav bar mode and display rotation.
+ */
+ public NavBarPosition getNavBarPosition() {
+ return mNavBarPosition;
+ }
+
+ /**
* @return whether the current nav mode is fully gestural.
*/
public boolean isFullyGesturalNavMode() {
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 465d464..f248423 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -25,11 +25,9 @@
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.Context;
-import android.content.pm.LauncherApps;
import android.os.Build;
import android.os.Looper;
import android.os.Process;
-import android.os.UserHandle;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.shared.recents.model.Task;
@@ -48,8 +46,6 @@
@TargetApi(Build.VERSION_CODES.O)
public class RecentsModel extends TaskStackChangeListener {
- private static final String TAG = "RecentsModel";
-
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
new MainThreadInitializedObject<>(RecentsModel::new);
@@ -70,7 +66,6 @@
mIconCache = new TaskIconCache(context, looper);
mThumbnailCache = new TaskThumbnailCache(context, looper);
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
- setupPackageListener();
}
public TaskIconCache getIconCache() {
@@ -183,35 +178,6 @@
}
}
- public void onOverviewShown(boolean fromHome, String tag) {
- SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(fromHome, tag);
- }
-
- private void setupPackageListener() {
- mContext.getSystemService(LauncherApps.class).registerCallback(new LauncherApps.Callback() {
- @Override
- public void onPackageRemoved(String packageName, UserHandle user) {
- mIconCache.invalidatePackage(packageName);
- }
-
- @Override
- public void onPackageChanged(String packageName, UserHandle user) {
- mIconCache.invalidatePackage(packageName);
- }
-
- @Override
- public void onPackageAdded(String packageName, UserHandle user) { }
-
- @Override
- public void onPackagesAvailable(
- String[] packageNames, UserHandle user, boolean replacing) { }
-
- @Override
- public void onPackagesUnavailable(
- String[] packageNames, UserHandle user, boolean replacing) { }
- });
- }
-
public void addThumbnailChangeListener(TaskThumbnailChangeListener listener) {
mThumbnailChangeListeners.add(listener);
}
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index 4f7d53b..873f29c 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -18,64 +18,58 @@
import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import android.content.ComponentName;
+import android.app.ActivityManager.TaskDescription;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
-import android.util.LruCache;
+import android.os.UserHandle;
+import android.util.SparseArray;
import android.view.accessibility.AccessibilityManager;
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.graphics.DrawableFactory;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.PackageManagerWrapper;
-import java.util.Map;
import java.util.function.Consumer;
/**
* Manages the caching of task icons and related data.
- * TODO(b/138944598): This class should later be merged into IconCache.
*/
public class TaskIconCache {
private final Handler mBackgroundHandler;
private final AccessibilityManager mAccessibilityManager;
- private final NormalizedIconLoader mIconLoader;
-
- private final TaskKeyLruCache<Drawable> mIconCache;
- private final TaskKeyLruCache<String> mContentDescriptionCache;
- private final LruCache<ComponentName, ActivityInfo> mActivityInfoCache;
-
- private TaskKeyLruCache.EvictionCallback mClearActivityInfoOnEviction =
- new TaskKeyLruCache.EvictionCallback() {
- @Override
- public void onEntryEvicted(Task.TaskKey key) {
- if (key != null) {
- mActivityInfoCache.remove(key.getComponent());
- }
- }
- };
+ private final Context mContext;
+ private final TaskKeyLruCache<TaskCacheEntry> mIconCache;
+ private final SparseArray<BitmapInfo> mDefaultIcons = new SparseArray<>();
public TaskIconCache(Context context, Looper backgroundLooper) {
+ mContext = context;
mBackgroundHandler = new Handler(backgroundLooper);
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
Resources res = context.getResources();
int cacheSize = res.getInteger(R.integer.recentsIconCacheSize);
- mIconCache = new TaskKeyLruCache<>(cacheSize, mClearActivityInfoOnEviction);
- mContentDescriptionCache = new TaskKeyLruCache<>(cacheSize, mClearActivityInfoOnEviction);
- mActivityInfoCache = new LruCache<>(cacheSize);
- mIconLoader = new NormalizedIconLoader(context, mIconCache, mActivityInfoCache,
- true /* disableColorExtraction */);
+ mIconCache = new TaskKeyLruCache<>(cacheSize);
}
/**
@@ -96,15 +90,14 @@
IconLoadRequest request = new IconLoadRequest(mBackgroundHandler) {
@Override
public void run() {
- Drawable icon = mIconLoader.getIcon(task);
- String contentDescription = loadContentDescriptionInBackground(task);
+ TaskCacheEntry entry = getCacheEntry(task);
if (isCanceled()) {
// We don't call back to the provided callback in this case
return;
}
MAIN_EXECUTOR.execute(() -> {
- task.icon = icon;
- task.titleDescription = contentDescription;
+ task.icon = entry.icon;
+ task.titleDescription = entry.contentDescription;
callback.accept(task);
onEnd();
});
@@ -116,51 +109,94 @@
public void clear() {
mIconCache.evictAll();
- mContentDescriptionCache.evictAll();
}
- /**
- * Loads the content description for the given {@param task}.
- */
- private String loadContentDescriptionInBackground(Task task) {
- // Return the cached content description if it exists
- String label = mContentDescriptionCache.getAndInvalidateIfModified(task.key);
- if (label != null) {
- return label;
- }
-
- // Skip loading content descriptions if accessibility is disabled unless low RAM recents
- // is enabled.
- if (!GO_LOW_RAM_RECENTS_ENABLED && !mAccessibilityManager.isEnabled()) {
- return "";
- }
-
- // Skip loading the content description if the activity no longer exists
- ActivityInfo activityInfo = mIconLoader.getAndUpdateActivityInfo(task.key);
- if (activityInfo == null) {
- return "";
- }
-
- // Load the label otherwise
- label = ActivityManagerWrapper.getInstance().getBadgedContentDescription(activityInfo,
- task.key.userId, task.taskDescription);
- mContentDescriptionCache.put(task.key, label);
- return label;
- }
-
-
void onTaskRemoved(TaskKey taskKey) {
mIconCache.remove(taskKey);
}
- void invalidatePackage(String packageName) {
- // TODO(b/138944598): Merge this class into IconCache so we can do this at the base level
- Map<ComponentName, ActivityInfo> activityInfoCache = mActivityInfoCache.snapshot();
- for (ComponentName cn : activityInfoCache.keySet()) {
- if (cn.getPackageName().equals(packageName)) {
- mActivityInfoCache.remove(cn);
+ @WorkerThread
+ private TaskCacheEntry getCacheEntry(Task task) {
+ TaskCacheEntry entry = mIconCache.getAndInvalidateIfModified(task.key);
+ if (entry != null) {
+ return entry;
+ }
+
+ TaskDescription desc = task.taskDescription;
+ TaskKey key = task.key;
+ ActivityInfo activityInfo = null;
+
+ // Create new cache entry
+ entry = new TaskCacheEntry();
+
+ // Load icon
+ // TODO: Load icon resource (b/143363444)
+ Bitmap icon = desc.getIcon();
+ if (icon != null) {
+ entry.icon = new FastBitmapDrawable(getBitmapInfo(
+ new BitmapDrawable(mContext.getResources(), icon),
+ key.userId,
+ desc.getPrimaryColor(),
+ false /* isInstantApp */));
+ } else {
+ activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(
+ key.getComponent(), key.userId);
+ if (activityInfo != null) {
+ BitmapInfo bitmapInfo = getBitmapInfo(
+ activityInfo.loadUnbadgedIcon(mContext.getPackageManager()),
+ key.userId,
+ desc.getPrimaryColor(),
+ activityInfo.applicationInfo.isInstantApp());
+ entry.icon = DrawableFactory.INSTANCE.get(mContext).newIcon(
+ mContext, bitmapInfo, activityInfo);
+ } else {
+ entry.icon = getDefaultIcon(key.userId);
}
}
+
+ // Loading content descriptions if accessibility or low RAM recents is enabled.
+ if (GO_LOW_RAM_RECENTS_ENABLED || mAccessibilityManager.isEnabled()) {
+ // Skip loading the content description if the activity no longer exists
+ if (activityInfo == null) {
+ activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(
+ key.getComponent(), key.userId);
+ }
+ if (activityInfo != null) {
+ entry.contentDescription = ActivityManagerWrapper.getInstance()
+ .getBadgedContentDescription(activityInfo, task.key.userId,
+ task.taskDescription);
+ }
+ }
+
+ mIconCache.put(task.key, entry);
+ return entry;
+ }
+
+ @WorkerThread
+ private Drawable getDefaultIcon(int userId) {
+ synchronized (mDefaultIcons) {
+ BitmapInfo info = mDefaultIcons.get(userId);
+ if (info == null) {
+ try (LauncherIcons la = LauncherIcons.obtain(mContext)) {
+ info = la.makeDefaultIcon(UserHandle.of(userId));
+ }
+ mDefaultIcons.put(userId, info);
+ }
+ return new FastBitmapDrawable(info);
+ }
+ }
+
+ @WorkerThread
+ private BitmapInfo getBitmapInfo(Drawable drawable, int userId,
+ int primaryColor, boolean isInstantApp) {
+ try (LauncherIcons la = LauncherIcons.obtain(mContext)) {
+ la.disableColorExtraction();
+ la.setWrapperBackgroundColor(primaryColor);
+
+ // User version code O, so that the icon is always wrapped in an adaptive icon container
+ return la.createBadgedIconBitmap(drawable, UserHandle.of(userId),
+ Build.VERSION_CODES.O, isInstantApp);
+ }
}
public static abstract class IconLoadRequest extends HandlerRunnable {
@@ -168,4 +204,9 @@
super(handler, null);
}
}
+
+ private static class TaskCacheEntry {
+ public Drawable icon;
+ public String contentDescription = "";
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
new file mode 100644
index 0000000..a4614de
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.Gravity;
+import android.view.Surface;
+
+import com.android.launcher3.graphics.RotationMode;
+import com.android.launcher3.util.DefaultDisplay;
+import com.android.quickstep.SysUINavigationMode;
+
+/**
+ * Utility class to check nav bar position.
+ */
+public class NavBarPosition {
+
+ public static RotationMode ROTATION_LANDSCAPE = new RotationMode(-90) {
+ @Override
+ public void mapRect(int left, int top, int right, int bottom, Rect out) {
+ out.left = top;
+ out.top = right;
+ out.right = bottom;
+ out.bottom = left;
+ }
+
+ @Override
+ public void mapInsets(Context context, Rect insets, Rect out) {
+ // If there is a display cutout, the top insets in portrait would also include the
+ // cutout, which we will get as the left inset in landscape. Using the max of left and
+ // top allows us to cover both cases (with or without cutout).
+ if (SysUINavigationMode.getMode(context) == NO_BUTTON) {
+ out.top = Math.max(insets.top, insets.left);
+ out.bottom = Math.max(insets.right, insets.bottom);
+ out.left = out.right = 0;
+ } else {
+ out.top = Math.max(insets.top, insets.left);
+ out.bottom = insets.right;
+ out.left = insets.bottom;
+ out.right = 0;
+ }
+ }
+ };
+
+ public static RotationMode ROTATION_SEASCAPE = new RotationMode(90) {
+ @Override
+ public void mapRect(int left, int top, int right, int bottom, Rect out) {
+ out.left = bottom;
+ out.top = left;
+ out.right = top;
+ out.bottom = right;
+ }
+
+ @Override
+ public void mapInsets(Context context, Rect insets, Rect out) {
+ if (SysUINavigationMode.getMode(context) == NO_BUTTON) {
+ out.top = Math.max(insets.top, insets.right);
+ out.bottom = Math.max(insets.left, insets.bottom);
+ out.left = out.right = 0;
+ } else {
+ out.top = Math.max(insets.top, insets.right);
+ out.bottom = insets.left;
+ out.right = insets.bottom;
+ out.left = 0;
+ }
+ }
+
+ @Override
+ public int toNaturalGravity(int absoluteGravity) {
+ int horizontalGravity = absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ int verticalGravity = absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK;
+
+ if (horizontalGravity == Gravity.RIGHT) {
+ horizontalGravity = Gravity.LEFT;
+ } else if (horizontalGravity == Gravity.LEFT) {
+ horizontalGravity = Gravity.RIGHT;
+ }
+
+ if (verticalGravity == Gravity.TOP) {
+ verticalGravity = Gravity.BOTTOM;
+ } else if (verticalGravity == Gravity.BOTTOM) {
+ verticalGravity = Gravity.TOP;
+ }
+
+ return ((absoluteGravity & ~Gravity.HORIZONTAL_GRAVITY_MASK)
+ & ~Gravity.VERTICAL_GRAVITY_MASK)
+ | horizontalGravity | verticalGravity;
+ }
+ };
+
+ private final SysUINavigationMode.Mode mMode;
+ private final int mDisplayRotation;
+
+ public NavBarPosition(SysUINavigationMode.Mode mode, DefaultDisplay.Info info) {
+ mMode = mode;
+ mDisplayRotation = info.rotation;
+ }
+
+ public boolean isRightEdge() {
+ return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
+ }
+
+ public boolean isLeftEdge() {
+ return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
+ }
+
+ public RotationMode getRotationMode() {
+ return isLeftEdge() ? ROTATION_SEASCAPE
+ : (isRightEdge() ? ROTATION_LANDSCAPE : RotationMode.NORMAL);
+ }
+}
diff --git a/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java b/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
index 32eb2ec..5b6d94d 100644
--- a/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
+++ b/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
@@ -202,15 +202,14 @@
CacheEntry entry = mCache.get(new ComponentKey(componentName, user));
if (entry == null) {
entry = new CacheEntry();
- getDefaultIcon(user).applyTo(entry);
+ entry.bitmap = getDefaultIcon(user);
}
return entry;
}
public void addCache(ComponentName key, String title) {
CacheEntry entry = new CacheEntry();
- entry.icon = newIcon();
- entry.color = Color.RED;
+ entry.bitmap = BitmapInfo.of(newIcon(), Color.RED);
entry.title = title;
mCache.put(new ComponentKey(key, Process.myUserHandle()), entry);
}
diff --git a/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index 81b9043..69c5b00 100644
--- a/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -2,13 +2,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import com.android.launcher3.AppInfo;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.WorkspaceItemInfo;
+import com.android.launcher3.icons.BitmapInfo;
import org.junit.Before;
import org.junit.Test;
@@ -43,7 +43,7 @@
public void testCacheUpdate_update_apps() throws Exception {
// Clear all icons from apps list so that its easy to check what was updated
for (AppInfo info : allAppsList.data) {
- info.iconBitmap = null;
+ info.bitmap = BitmapInfo.LOW_RES_INFO;
}
executeTaskForTest(newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, "app1"));
@@ -56,9 +56,9 @@
assertFalse(allAppsList.data.isEmpty());
for (AppInfo info : allAppsList.data) {
if (info.componentName.getPackageName().equals("app1")) {
- assertNotNull(info.iconBitmap);
+ assertFalse(info.bitmap.isNullOrLowRes());
} else {
- assertNull(info.iconBitmap);
+ assertTrue(info.bitmap.isNullOrLowRes());
}
}
}
@@ -85,10 +85,10 @@
for (ItemInfo info : bgDataModel.itemsIdMap) {
if (updates.contains(info.id)) {
assertEquals(NEW_LABEL_PREFIX + info.id, info.title);
- assertNotNull(((WorkspaceItemInfo) info).iconBitmap);
+ assertFalse(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
} else {
assertNotSame(NEW_LABEL_PREFIX + info.id, info.title);
- assertNull(((WorkspaceItemInfo) info).iconBitmap);
+ assertTrue(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
}
}
}
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index d24de8e..772eb00 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -57,7 +57,7 @@
private ActionMode mCurrentActionMode;
protected boolean mIsSafeModeEnabled;
- private OnStartCallback mOnStartCallback;
+ private Runnable mOnStartCallback;
private int mThemeRes = R.style.AppTheme;
@@ -226,7 +226,7 @@
super.onStart();
if (mOnStartCallback != null) {
- mOnStartCallback.onActivityStart(this);
+ mOnStartCallback.run();
mOnStartCallback = null;
}
}
@@ -238,8 +238,12 @@
mRotationListener.disable();
}
- public <T extends BaseDraggingActivity> void setOnStartCallback(OnStartCallback<T> callback) {
- mOnStartCallback = callback;
+ public void runOnceOnStart(Runnable action) {
+ mOnStartCallback = action;
+ }
+
+ public void clearRunOnceOnStartCallback() {
+ mOnStartCallback = null;
}
protected void onDeviceProfileInitiated() {
@@ -258,12 +262,4 @@
}
protected abstract void reapplyUi();
-
- /**
- * Callback for listening for onStart
- */
- public interface OnStartCallback<T extends BaseDraggingActivity> {
-
- void onActivityStart(T activity);
- }
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 7adb6a4..e8aa83f 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -289,7 +289,7 @@
private void applyIconAndLabel(ItemInfoWithIcon info) {
FastBitmapDrawable iconDrawable = DrawableFactory.INSTANCE.get(getContext())
.newIcon(getContext(), info);
- mDotParams.color = IconPalette.getMutedColor(info.iconColor, 0.54f);
+ mDotParams.color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
setIcon(iconDrawable);
setText(info.title);
@@ -665,7 +665,7 @@
mDisableRelayout = true;
// Optimization: Starting in N, pre-uploads the bitmap to RenderThread.
- info.iconBitmap.prepareToDraw();
+ info.bitmap.icon.prepareToDraw();
if (info instanceof AppInfo) {
applyFromApplicationInfo((AppInfo) info);
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index a90025e..2e57f71 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -98,10 +98,6 @@
this(info.icon, info.color);
}
- public FastBitmapDrawable(ItemInfoWithIcon info) {
- this(info.iconBitmap, info.iconColor);
- }
-
protected FastBitmapDrawable(Bitmap b, int iconColor) {
this(b, iconColor, false);
}
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 93def50..125332d 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -21,6 +21,7 @@
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -39,6 +40,7 @@
import android.util.Log;
import android.util.Pair;
+import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.android.launcher3.compat.UserManagerCompat;
@@ -238,11 +240,6 @@
return info == null ? null : (WorkspaceItemInfo) info.getItemInfo().first;
}
- public static WorkspaceItemInfo fromActivityInfo(LauncherActivityInfo info, Context context) {
- return (WorkspaceItemInfo)
- new PendingInstallShortcutInfo(info, context).getItemInfo().first;
- }
-
public static void queueShortcut(ShortcutInfo info, Context context) {
queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, context), context);
}
@@ -318,10 +315,10 @@
private static class PendingInstallShortcutInfo {
final boolean isActivity;
- final ShortcutInfo shortcutInfo;
- final AppWidgetProviderInfo providerInfo;
+ @Nullable final ShortcutInfo shortcutInfo;
+ @Nullable final AppWidgetProviderInfo providerInfo;
- final Intent data;
+ @Nullable final Intent data;
final Context mContext;
final Intent launchIntent;
final String label;
@@ -351,7 +348,12 @@
shortcutInfo = null;
providerInfo = null;
- data = null;
+ String packageName = info.getComponentName().getPackageName();
+ data = new Intent();
+ data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent().setComponent(
+ new ComponentName(packageName, "")).setPackage(packageName));
+ data.putExtra(Intent.EXTRA_SHORTCUT_NAME, info.getLabel());
+
user = info.getUser();
mContext = context;
@@ -445,9 +447,10 @@
// This name is only used for comparisons and notifications, so fall back to activity
// name if not supplied
String name = ensureValidName(mContext, launchIntent, label).toString();
- Bitmap icon = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
- Intent.ShortcutIconResource iconResource =
- data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
+ Bitmap icon = data == null ? null
+ : data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
+ Intent.ShortcutIconResource iconResource = data == null ? null
+ : data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
// Only encode the parameters which are supported by the API.
JSONStringer json = new JSONStringer()
@@ -459,9 +462,11 @@
.key(APP_SHORTCUT_TYPE_KEY).value(isActivity);
if (icon != null) {
byte[] iconByteArray = GraphicsUtils.flattenBitmap(icon);
- json = json.key(ICON_KEY).value(
- Base64.encodeToString(
- iconByteArray, 0, iconByteArray.length, Base64.DEFAULT));
+ if (iconByteArray != null) {
+ json = json.key(ICON_KEY).value(
+ Base64.encodeToString(
+ iconByteArray, 0, iconByteArray.length, Base64.DEFAULT));
+ }
}
if (iconResource != null) {
json = json.key(ICON_RESOURCE_NAME_KEY).value(iconResource.resourceName);
@@ -485,7 +490,7 @@
} else if (shortcutInfo != null) {
WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, mContext);
LauncherIcons li = LauncherIcons.obtain(mContext);
- itemInfo.applyFrom(li.createShortcutIcon(shortcutInfo));
+ itemInfo.bitmap = li.createShortcutIcon(shortcutInfo);
li.recycle();
return Pair.create(itemInfo, shortcutInfo);
} else if (providerInfo != null) {
@@ -656,7 +661,7 @@
if (iconInfo == null) {
iconInfo = app.getIconCache().getDefaultIcon(info.user);
}
- info.applyFrom(iconInfo);
+ info.bitmap = iconInfo;
info.title = Utilities.trim(name);
info.contentDescription = app.getContext().getPackageManager()
diff --git a/src/com/android/launcher3/ItemInfoWithIcon.java b/src/com/android/launcher3/ItemInfoWithIcon.java
index 1550bb0..1941455 100644
--- a/src/com/android/launcher3/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/ItemInfoWithIcon.java
@@ -16,10 +16,6 @@
package com.android.launcher3;
-import static com.android.launcher3.icons.BitmapInfo.LOW_RES_ICON;
-
-import android.graphics.Bitmap;
-
import com.android.launcher3.icons.BitmapInfo;
/**
@@ -30,14 +26,9 @@
public static final String TAG = "ItemInfoDebug";
/**
- * A bitmap version of the application icon.
+ * The bitmap for the application icon
*/
- public Bitmap iconBitmap;
-
- /**
- * Dominant color in the {@link #iconBitmap}.
- */
- public int iconColor;
+ public BitmapInfo bitmap = BitmapInfo.LOW_RES_INFO;
/**
* Indicates that the icon is disabled due to safe mode restrictions.
@@ -106,8 +97,7 @@
protected ItemInfoWithIcon(ItemInfoWithIcon info) {
super(info);
- iconBitmap = info.iconBitmap;
- iconColor = info.iconColor;
+ bitmap = info.bitmap;
runtimeStatusFlags = info.runtimeStatusFlags;
}
@@ -120,12 +110,7 @@
* Indicates whether we're using a low res icon
*/
public boolean usingLowResIcon() {
- return iconBitmap == LOW_RES_ICON;
- }
-
- public void applyFrom(BitmapInfo info) {
- iconBitmap = info.icon;
- iconColor = info.color;
+ return bitmap.isLowRes();
}
/**
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index fc2e953..93304a1 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -93,10 +93,6 @@
private boolean mModelLoaded;
public boolean isModelLoaded() {
synchronized (mLock) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "isModelLoaded: " + mModelLoaded + ", " + mLoaderTask);
- }
return mModelLoaded && mLoaderTask == null;
}
}
@@ -326,9 +322,6 @@
public void stopLoader() {
synchronized (mLock) {
LoaderTask oldTask = mLoaderTask;
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, "LauncherModel.stopLoader");
- }
mLoaderTask = null;
if (oldTask != null) {
oldTask.stopLocked();
@@ -340,10 +333,6 @@
synchronized (mLock) {
stopLoader();
mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "LauncherModel.startLoaderForResults " + mLoaderTask);
- }
// Always post the loader task, instead of running directly (even on same thread) so
// that we exit any nested synchronized blocks
@@ -445,10 +434,6 @@
public void close() {
synchronized (mLock) {
// If we are still the last one to be scheduled, remove ourselves.
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "LauncherModel.close " + mLoaderTask + ", " + mTask);
- }
if (mLoaderTask == mTask) {
mLoaderTask = null;
}
@@ -525,7 +510,7 @@
updateAndBindWorkspaceItem(() -> {
si.updateFromDeepShortcutInfo(info, mApp.getContext());
LauncherIcons li = LauncherIcons.obtain(mApp.getContext());
- si.applyFrom(li.createShortcutIcon(info));
+ si.bitmap = li.createShortcutIcon(info);
li.recycle();
return si;
});
@@ -561,7 +546,8 @@
if (args.length > 0 && TextUtils.equals(args[0], "--all")) {
writer.println(prefix + "All apps list: size=" + mBgAllAppsList.data.size());
for (AppInfo info : mBgAllAppsList.data) {
- writer.println(prefix + " title=\"" + info.title + "\" iconBitmap=" + info.iconBitmap
+ writer.println(prefix + " title=\"" + info.title
+ + "\" bitmapIcon=" + info.bitmap.icon
+ " componentName=" + info.componentName.getPackageName());
}
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 92f8069..aa6e61c 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -582,7 +582,7 @@
}
ShortcutInfo si = (ShortcutInfo) obj;
LauncherIcons li = LauncherIcons.obtain(appState.getContext());
- Bitmap badge = li.getShortcutInfoBadge(si, appState.getIconCache()).iconBitmap;
+ Bitmap badge = li.getShortcutInfoBadge(si, appState.getIconCache()).bitmap.icon;
li.recycle();
float badgeSize = iconSize * LauncherIcons.getBadgeSizeForIconSize(iconSize);
float insetFraction = (iconSize - badgeSize) / iconSize;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index eca5d12..431a149 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1471,9 +1471,6 @@
public DragView beginDragShared(View child, DragSource source, ItemInfo dragObject,
DragPreviewProvider previewProvider, DragOptions dragOptions) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_CONTEXT_MENU, "beginDragShared");
- }
float iconScale = 1f;
if (child instanceof BubbleTextView) {
Drawable icon = ((BubbleTextView) child).getIcon();
diff --git a/src/com/android/launcher3/WorkspaceItemInfo.java b/src/com/android/launcher3/WorkspaceItemInfo.java
index 71bd92f..be907e5 100644
--- a/src/com/android/launcher3/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/WorkspaceItemInfo.java
@@ -140,7 +140,7 @@
.put(Favorites.RESTORED, status);
if (!usingLowResIcon()) {
- writer.putIcon(iconBitmap, user);
+ writer.putIcon(bitmap, user);
}
if (iconResource != null) {
writer.put(Favorites.ICON_PACKAGE, iconResource.packageName)
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 4abdbef..d7543ab 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -120,6 +120,10 @@
public static final TogglableFlag ENABLE_QUICK_CAPTURE_GESTURE = new TogglableFlag(
"ENABLE_QUICK_CAPTURE_GESTURE", false, "Swipe from right to left to quick capture");
+ public static final TogglableFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = new TogglableFlag(
+ "ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
+ "Allow Launcher to handle nav bar gestures while Assistant is running over it");
+
public static void initialize(Context context) {
// Avoid the disk read for user builds
if (Utilities.IS_DEBUG_DEVICE) {
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
index 837301f..13dbab5 100644
--- a/src/com/android/launcher3/graphics/DrawableFactory.java
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -57,8 +57,8 @@
*/
public FastBitmapDrawable newIcon(Context context, ItemInfoWithIcon info) {
FastBitmapDrawable drawable = info.usingLowResIcon()
- ? new PlaceHolderIconDrawable(info, getShapePath(), context)
- : new FastBitmapDrawable(info);
+ ? new PlaceHolderIconDrawable(info.bitmap, getShapePath(), context)
+ : new FastBitmapDrawable(info.bitmap);
drawable.setIsDisabled(info.isDisabled());
return drawable;
}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index d7b845b..2badb6e 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -50,8 +50,8 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
-import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.Utilities;
+import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.WorkspaceLayoutManager;
import com.android.launcher3.allapps.SearchUiManager;
import com.android.launcher3.config.FeatureFlags;
@@ -105,7 +105,7 @@
Build.VERSION.SDK_INT);
mWorkspaceItemInfo = new WorkspaceItemInfo();
- mWorkspaceItemInfo.applyFrom(iconInfo);
+ mWorkspaceItemInfo.bitmap = iconInfo;
mWorkspaceItemInfo.intent = new Intent();
mWorkspaceItemInfo.contentDescription = mWorkspaceItemInfo.title =
context.getString(R.string.label_application);
diff --git a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
index 23745cb..c6f807f 100644
--- a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
@@ -24,7 +24,6 @@
import android.graphics.Rect;
import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.util.Themes;
@@ -41,10 +40,6 @@
this(info.icon, info.color, progressPath, context);
}
- public PlaceHolderIconDrawable(ItemInfoWithIcon info, Path progressPath, Context context) {
- this(info.iconBitmap, info.iconColor, progressPath, context);
- }
-
protected PlaceHolderIconDrawable(Bitmap b, int iconColor, Path progressPath, Context context) {
super(b, iconColor);
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index cc4c2ef..acdf942 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -105,7 +105,7 @@
* @param progressPath fixed path in the bounds [0, 0, 100, 100] representing a progress bar.
*/
public PreloadIconDrawable(ItemInfoWithIcon info, Path progressPath, Context context) {
- super(info);
+ super(info.bitmap);
mItem = info;
mProgressPath = progressPath;
mScaledTrackPath = new Path();
diff --git a/src/com/android/launcher3/icons/ComponentWithLabel.java b/src/com/android/launcher3/icons/ComponentWithLabel.java
index 832956d..f7ee5f9 100644
--- a/src/com/android/launcher3/icons/ComponentWithLabel.java
+++ b/src/com/android/launcher3/icons/ComponentWithLabel.java
@@ -57,10 +57,8 @@
}
@Override
- public void loadIcon(Context context,
- ComponentWithLabel object, BitmapInfo target) {
- // Do not load icon.
- target.icon = BitmapInfo.LOW_RES_ICON;
+ public BitmapInfo loadIcon(Context context, ComponentWithLabel object) {
+ return BitmapInfo.LOW_RES_INFO;
}
@Override
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 9886f53..13dc08f 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -161,7 +161,7 @@
CacheEntry entry = cacheLocked(application.componentName,
application.user, () -> null, mLauncherActivityInfoCachingLogic,
false, application.usingLowResIcon());
- if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) {
+ if (entry.bitmap != null && !isDefaultIcon(entry.bitmap, application.user)) {
applyCacheEntry(entry, application);
}
}
@@ -183,7 +183,7 @@
// null info means not installed, but if we have a component from the intent then
// we should still look in the cache for restored app icons.
if (info.getTargetComponent() == null) {
- info.applyFrom(getDefaultIcon(info.user));
+ info.bitmap = getDefaultIcon(info.user);
info.title = "";
info.contentDescription = "";
} else {
@@ -226,7 +226,7 @@
protected void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
info.title = Utilities.trim(entry.title);
info.contentDescription = entry.contentDescription;
- info.applyFrom((entry.icon == null) ? getDefaultIcon(info.user) : entry);
+ info.bitmap = (entry.bitmap == null) ? getDefaultIcon(info.user) : entry.bitmap;
}
public Drawable getFullResIcon(LauncherActivityInfo info) {
diff --git a/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java b/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
index f9a94da..a29d4fe 100644
--- a/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
+++ b/src/com/android/launcher3/icons/LauncherActivityCachingLogic.java
@@ -55,13 +55,12 @@
}
@Override
- public void loadIcon(Context context, LauncherActivityInfo object,
- BitmapInfo target) {
- LauncherIcons li = LauncherIcons.obtain(context);
- li.createBadgedIconBitmap(
- IconProvider.INSTANCE.get(context)
- .getIcon(object, li.mFillResIconDpi, true /* flattenDrawable */),
- object.getUser(), object.getApplicationInfo().targetSdkVersion).applyTo(target);
- li.recycle();
+ public BitmapInfo loadIcon(Context context, LauncherActivityInfo object) {
+ try (LauncherIcons li = LauncherIcons.obtain(context)) {
+ return li.createBadgedIconBitmap(
+ IconProvider.INSTANCE.get(context)
+ .getIcon(object, li.mFillResIconDpi, true /* flattenDrawable */),
+ object.getUser(), object.getApplicationInfo().targetSdkVersion);
+ }
}
}
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index adc92c4..1c34dc4 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -137,32 +137,25 @@
if (fallbackIconProvider != null) {
// Fallback icons are already badged and with appropriate shadow
ItemInfoWithIcon fullIcon = fallbackIconProvider.get();
- if (fullIcon != null && fullIcon.iconBitmap != null) {
- BitmapInfo result = new BitmapInfo();
- result.icon = fullIcon.iconBitmap;
- result.color = fullIcon.iconColor;
- return result;
+ if (fullIcon != null && fullIcon.bitmap != null) {
+ return fullIcon.bitmap;
}
}
unbadgedBitmap = cache.getDefaultIcon(Process.myUserHandle()).icon;
}
- BitmapInfo result = new BitmapInfo();
if (!badged) {
- result.color = Themes.getColorAccent(mContext);
- result.icon = unbadgedBitmap;
- return result;
+ return BitmapInfo.of(unbadgedBitmap, Themes.getColorAccent(mContext));
}
final Bitmap unbadgedfinal = unbadgedBitmap;
final ItemInfoWithIcon badge = getShortcutInfoBadge(shortcutInfo, cache);
- result.color = badge.iconColor;
- result.icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> {
+ Bitmap icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> {
getShadowGenerator().recreateIcon(unbadgedfinal, c);
- badgeWithDrawable(c, new FastBitmapDrawable(badge));
+ badgeWithDrawable(c, new FastBitmapDrawable(badge.bitmap));
});
- return result;
+ return BitmapInfo.of(icon, badge.bitmap.color);
}
public ItemInfoWithIcon getShortcutInfoBadge(ShortcutInfo shortcutInfo, IconCache cache) {
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 2d62c9e..21c73e9 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -137,7 +137,7 @@
.makeWorkspaceItem();
WorkspaceItemInfo wii = (WorkspaceItemInfo) itemInfo;
wii.title = "";
- wii.applyFrom(app.getIconCache().getDefaultIcon(item.user));
+ wii.bitmap = app.getIconCache().getDefaultIcon(item.user);
app.getIconCache().getTitleAndIcon(wii,
((WorkspaceItemInfo) itemInfo).usingLowResIcon());
}
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 6154e7e..95268d0 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -153,7 +153,7 @@
info.title = getTitle();
// the fallback icon
if (!loadIcon(info)) {
- info.applyFrom(mIconCache.getDefaultIcon(info.user));
+ info.bitmap = mIconCache.getDefaultIcon(info.user);
}
// TODO: If there's an explicit component and we can't install that, delete it.
@@ -183,7 +183,7 @@
info.iconResource.resourceName = resourceName;
BitmapInfo iconInfo = li.createIconBitmap(info.iconResource);
if (iconInfo != null) {
- info.applyFrom(iconInfo);
+ info.bitmap = iconInfo;
return true;
}
}
@@ -192,7 +192,7 @@
// Failed to load from resource, try loading from DB.
byte[] data = getBlob(iconIndex);
try {
- info.applyFrom(li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length)));
+ info.bitmap = li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
return true;
} catch (Exception e) {
Log.e(TAG, "Failed to decode byte array for info " + info, e);
@@ -273,7 +273,7 @@
info.intent = newIntent;
mIconCache.getTitleAndIcon(info, lai, useLowResIcon);
- if (mIconCache.isDefaultIcon(info.iconBitmap, user)) {
+ if (mIconCache.isDefaultIcon(info.bitmap, user)) {
loadIcon(info);
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 04f15fc..6383a5f 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -164,32 +164,15 @@
}
public void run() {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "LoaderTask1 " + this);
- }
synchronized (this) {
// Skip fast if we are already stopped.
if (mStopped) {
return;
}
}
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "LoaderTask2 " + this);
- }
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
- TimingLogger logger = TestProtocol.sDebugTracing ?
- new TimingLogger(TAG, "run") {
- @Override
- public void addSplit(String splitLabel) {
- super.addSplit(splitLabel);
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "LoaderTask.addSplit " + splitLabel);
- }
- }
- : new TimingLogger(TAG, "run");
+ TimingLogger logger = new TimingLogger(TAG, "run");
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
loadWorkspace();
logger.addSplit("loadWorkspace");
@@ -258,10 +241,6 @@
updateHandler.finish();
logger.addSplit("finish icon update");
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "LoaderTask3 " + this);
- }
transaction.commit();
} catch (CancellationException e) {
// Loader stopped, ignore
@@ -524,8 +503,9 @@
// use the last saved icon instead of the default.
Supplier<ItemInfoWithIcon> fallbackIconProvider = () ->
c.loadIcon(finalInfo, li) ? finalInfo : null;
- info.applyFrom(li.createShortcutIcon(pinnedShortcut,
- true /* badged */, fallbackIconProvider));
+ info.bitmap = li.createShortcutIcon(
+ pinnedShortcut, true /* badged */,
+ fallbackIconProvider);
li.recycle();
if (pmHelper.isAppSuspended(
pinnedShortcut.getPackage(), info.user)) {
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index db63b7c..1e614bd 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -189,7 +189,7 @@
BitmapInfo iconInfo = li.createIconBitmap(si.iconResource);
li.recycle();
if (iconInfo != null) {
- si.applyFrom(iconInfo);
+ si.bitmap = iconInfo;
infoUpdated = true;
}
}
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 6c358b1..05225d4 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -93,8 +93,8 @@
// If the shortcut is pinned but no longer has an icon in the system,
// keep the current icon instead of reverting to the default icon.
LauncherIcons li = LauncherIcons.obtain(context);
- workspaceItemInfo.applyFrom(li.createShortcutIcon(fullDetails, true,
- () -> workspaceItemInfo));
+ workspaceItemInfo.bitmap = li.createShortcutIcon(
+ fullDetails, true, () -> workspaceItemInfo);
li.recycle();
updatedWorkspaceItemInfos.add(workspaceItemInfo);
}
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 4b773d7..db1c307 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -92,7 +92,7 @@
// If the shortcut is pinned but no longer has an icon in the system,
// keep the current icon instead of reverting to the default icon.
LauncherIcons li = LauncherIcons.obtain(context);
- si.applyFrom(li.createShortcutIcon(shortcut, true, () -> si));
+ si.bitmap = li.createShortcutIcon(shortcut, true, () -> si);
li.recycle();
} else {
si.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 10378ee..0e73829 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -16,6 +16,7 @@
package com.android.launcher3.notification;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver;
@@ -32,9 +33,10 @@
import android.util.Log;
import android.util.Pair;
+import androidx.annotation.AnyThread;
import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
-import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.SecureSettingsObserver;
@@ -44,6 +46,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
/**
* A {@link NotificationListenerService} that sends updates to its
@@ -59,16 +62,17 @@
private static final int MSG_NOTIFICATION_POSTED = 1;
private static final int MSG_NOTIFICATION_REMOVED = 2;
private static final int MSG_NOTIFICATION_FULL_REFRESH = 3;
+ private static final int MSG_CANCEL_NOTIFICATION = 4;
+ private static final int MSG_RANKING_UPDATE = 5;
private static NotificationListener sNotificationListenerInstance = null;
private static NotificationsChangedListener sNotificationsChangedListener;
- private static StatusBarNotificationsChangedListener sStatusBarNotificationsChangedListener;
private static boolean sIsConnected;
- private static boolean sIsCreated;
private final Handler mWorkerHandler;
private final Handler mUiHandler;
private final Ranking mTempRanking = new Ranking();
+
/** Maps groupKey's to the corresponding group of notifications. */
private final Map<String, NotificationGroup> mNotificationGroupMap = new HashMap<>();
/** Maps keys to their corresponding current group key */
@@ -79,85 +83,12 @@
private SecureSettingsObserver mNotificationDotsObserver;
- private final Handler.Callback mWorkerCallback = new Handler.Callback() {
- @Override
- public boolean handleMessage(Message message) {
- switch (message.what) {
- case MSG_NOTIFICATION_POSTED:
- mUiHandler.obtainMessage(message.what, message.obj).sendToTarget();
- break;
- case MSG_NOTIFICATION_REMOVED:
- mUiHandler.obtainMessage(message.what, message.obj).sendToTarget();
- break;
- case MSG_NOTIFICATION_FULL_REFRESH:
- List<StatusBarNotification> activeNotifications;
- if (sIsConnected) {
- try {
- activeNotifications = filterNotifications(getActiveNotifications());
- } catch (SecurityException ex) {
- Log.e(TAG, "SecurityException: failed to fetch notifications");
- activeNotifications = new ArrayList<StatusBarNotification>();
-
- }
- } else {
- activeNotifications = new ArrayList<StatusBarNotification>();
- }
-
- mUiHandler.obtainMessage(message.what, activeNotifications).sendToTarget();
- break;
- }
- return true;
- }
- };
-
- private final Handler.Callback mUiCallback = new Handler.Callback() {
- @Override
- public boolean handleMessage(Message message) {
- switch (message.what) {
- case MSG_NOTIFICATION_POSTED:
- if (sNotificationsChangedListener != null) {
- NotificationPostedMsg msg = (NotificationPostedMsg) message.obj;
- sNotificationsChangedListener.onNotificationPosted(msg.packageUserKey,
- msg.notificationKey, msg.shouldBeFilteredOut);
- }
- break;
- case MSG_NOTIFICATION_REMOVED:
- if (sNotificationsChangedListener != null) {
- Pair<PackageUserKey, NotificationKeyData> pair
- = (Pair<PackageUserKey, NotificationKeyData>) message.obj;
- sNotificationsChangedListener.onNotificationRemoved(pair.first, pair.second);
- }
- break;
- case MSG_NOTIFICATION_FULL_REFRESH:
- if (sNotificationsChangedListener != null) {
- sNotificationsChangedListener.onNotificationFullRefresh(
- (List<StatusBarNotification>) message.obj);
- }
- break;
- }
- return true;
- }
- };
-
public NotificationListener() {
- super();
- mWorkerHandler = new Handler(MODEL_EXECUTOR.getLooper(), mWorkerCallback);
- mUiHandler = new Handler(Looper.getMainLooper(), mUiCallback);
+ mWorkerHandler = new Handler(MODEL_EXECUTOR.getLooper(), this::handleWorkerMessage);
+ mUiHandler = new Handler(Looper.getMainLooper(), this::handleUiMessage);
sNotificationListenerInstance = this;
}
- @Override
- public void onCreate() {
- super.onCreate();
- sIsCreated = true;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- sIsCreated = false;
- }
-
public static @Nullable NotificationListener getInstanceIfConnected() {
return sIsConnected ? sNotificationListenerInstance : null;
}
@@ -168,25 +99,107 @@
NotificationListener notificationListener = getInstanceIfConnected();
if (notificationListener != null) {
notificationListener.onNotificationFullRefresh();
- } else if (!sIsCreated && sNotificationsChangedListener != null) {
+ } else {
// User turned off dots globally, so we unbound this service;
// tell the listener that there are no notifications to remove dots.
- sNotificationsChangedListener.onNotificationFullRefresh(
- Collections.<StatusBarNotification>emptyList());
+ MODEL_EXECUTOR.submit(() -> MAIN_EXECUTOR.submit(() ->
+ listener.onNotificationFullRefresh(Collections.emptyList())));
}
}
- public static void setStatusBarNotificationsChangedListener
- (StatusBarNotificationsChangedListener listener) {
- sStatusBarNotificationsChangedListener = listener;
- }
-
public static void removeNotificationsChangedListener() {
sNotificationsChangedListener = null;
}
- public static void removeStatusBarNotificationsChangedListener() {
- sStatusBarNotificationsChangedListener = null;
+ private boolean handleWorkerMessage(Message message) {
+ switch (message.what) {
+ case MSG_NOTIFICATION_POSTED: {
+ StatusBarNotification sbn = (StatusBarNotification) message.obj;
+ mUiHandler.obtainMessage(shouldBeFilteredOut(sbn)
+ ? MSG_NOTIFICATION_REMOVED : MSG_NOTIFICATION_POSTED,
+ toKeyPair(sbn)).sendToTarget();
+ return true;
+ }
+ case MSG_NOTIFICATION_REMOVED: {
+ StatusBarNotification sbn = (StatusBarNotification) message.obj;
+ mUiHandler.obtainMessage(MSG_NOTIFICATION_REMOVED,
+ toKeyPair(sbn)).sendToTarget();
+
+ NotificationGroup notificationGroup = mNotificationGroupMap.get(sbn.getGroupKey());
+ String key = sbn.getKey();
+ if (notificationGroup != null) {
+ notificationGroup.removeChildKey(key);
+ if (notificationGroup.isEmpty()) {
+ if (key.equals(mLastKeyDismissedByLauncher)) {
+ // Only cancel the group notification if launcher dismissed the
+ // last child.
+ cancelNotification(notificationGroup.getGroupSummaryKey());
+ }
+ mNotificationGroupMap.remove(sbn.getGroupKey());
+ }
+ }
+ if (key.equals(mLastKeyDismissedByLauncher)) {
+ mLastKeyDismissedByLauncher = null;
+ }
+ return true;
+ }
+ case MSG_NOTIFICATION_FULL_REFRESH:
+ List<StatusBarNotification> activeNotifications = null;
+ if (sIsConnected) {
+ try {
+ activeNotifications = Arrays.stream(getActiveNotifications())
+ .filter(this::shouldBeFilteredOut)
+ .collect(Collectors.toList());
+ } catch (SecurityException ex) {
+ Log.e(TAG, "SecurityException: failed to fetch notifications");
+ activeNotifications = new ArrayList<>();
+ }
+ } else {
+ activeNotifications = new ArrayList<>();
+ }
+
+ mUiHandler.obtainMessage(message.what, activeNotifications).sendToTarget();
+ return true;
+ case MSG_CANCEL_NOTIFICATION: {
+ mLastKeyDismissedByLauncher = (String) message.obj;
+ cancelNotification(mLastKeyDismissedByLauncher);
+ return true;
+ }
+ case MSG_RANKING_UPDATE: {
+ String[] keys = ((RankingMap) message.obj).getOrderedKeys();
+ for (StatusBarNotification sbn : getActiveNotifications(keys)) {
+ updateGroupKeyIfNecessary(sbn);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean handleUiMessage(Message message) {
+ switch (message.what) {
+ case MSG_NOTIFICATION_POSTED:
+ if (sNotificationsChangedListener != null) {
+ Pair<PackageUserKey, NotificationKeyData> msg = (Pair) message.obj;
+ sNotificationsChangedListener.onNotificationPosted(
+ msg.first, msg.second);
+ }
+ break;
+ case MSG_NOTIFICATION_REMOVED:
+ if (sNotificationsChangedListener != null) {
+ Pair<PackageUserKey, NotificationKeyData> msg = (Pair) message.obj;
+ sNotificationsChangedListener.onNotificationRemoved(
+ msg.first, msg.second);
+ }
+ break;
+ case MSG_NOTIFICATION_FULL_REFRESH:
+ if (sNotificationsChangedListener != null) {
+ sNotificationsChangedListener.onNotificationFullRefresh(
+ (List<StatusBarNotification>) message.obj);
+ }
+ break;
+ }
+ return true;
}
@Override
@@ -217,84 +230,37 @@
super.onListenerDisconnected();
sIsConnected = false;
mNotificationDotsObserver.unregister();
+ onNotificationFullRefresh();
}
@Override
public void onNotificationPosted(final StatusBarNotification sbn) {
- super.onNotificationPosted(sbn);
- if (sbn == null) {
- // There is a bug in platform where we can get a null notification; just ignore it.
- return;
- }
- mWorkerHandler.obtainMessage(MSG_NOTIFICATION_POSTED, new NotificationPostedMsg(sbn))
- .sendToTarget();
- if (sStatusBarNotificationsChangedListener != null) {
- sStatusBarNotificationsChangedListener.onNotificationPosted(sbn);
- }
- }
-
- /**
- * An object containing data to send to MSG_NOTIFICATION_POSTED targets.
- */
- private class NotificationPostedMsg {
- final PackageUserKey packageUserKey;
- final NotificationKeyData notificationKey;
- final boolean shouldBeFilteredOut;
-
- NotificationPostedMsg(StatusBarNotification sbn) {
- packageUserKey = PackageUserKey.fromNotification(sbn);
- notificationKey = NotificationKeyData.fromNotification(sbn);
- shouldBeFilteredOut = shouldBeFilteredOut(sbn);
+ if (sbn != null) {
+ mWorkerHandler.obtainMessage(MSG_NOTIFICATION_POSTED, sbn).sendToTarget();
}
}
@Override
public void onNotificationRemoved(final StatusBarNotification sbn) {
- super.onNotificationRemoved(sbn);
- if (sbn == null) {
- // There is a bug in platform where we can get a null notification; just ignore it.
- return;
+ if (sbn != null) {
+ mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, sbn).sendToTarget();
}
- Pair<PackageUserKey, NotificationKeyData> packageUserKeyAndNotificationKey
- = new Pair<>(PackageUserKey.fromNotification(sbn),
- NotificationKeyData.fromNotification(sbn));
- mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, packageUserKeyAndNotificationKey)
- .sendToTarget();
- if (sStatusBarNotificationsChangedListener != null) {
- sStatusBarNotificationsChangedListener.onNotificationRemoved(sbn);
- }
-
- NotificationGroup notificationGroup = mNotificationGroupMap.get(sbn.getGroupKey());
- String key = sbn.getKey();
- if (notificationGroup != null) {
- notificationGroup.removeChildKey(key);
- if (notificationGroup.isEmpty()) {
- if (key.equals(mLastKeyDismissedByLauncher)) {
- // Only cancel the group notification if launcher dismissed the last child.
- cancelNotification(notificationGroup.getGroupSummaryKey());
- }
- mNotificationGroupMap.remove(sbn.getGroupKey());
- }
- }
- if (key.equals(mLastKeyDismissedByLauncher)) {
- mLastKeyDismissedByLauncher = null;
- }
- }
-
- public void cancelNotificationFromLauncher(String key) {
- mLastKeyDismissedByLauncher = key;
- cancelNotification(key);
}
@Override
public void onNotificationRankingUpdate(RankingMap rankingMap) {
- super.onNotificationRankingUpdate(rankingMap);
- String[] keys = rankingMap.getOrderedKeys();
- for (StatusBarNotification sbn : getActiveNotifications(keys)) {
- updateGroupKeyIfNecessary(sbn);
- }
+ mWorkerHandler.obtainMessage(MSG_RANKING_UPDATE, rankingMap).sendToTarget();
}
+ /**
+ * Cancels a notification
+ */
+ @AnyThread
+ public void cancelNotificationFromLauncher(String key) {
+ mWorkerHandler.obtainMessage(MSG_CANCEL_NOTIFICATION, key).sendToTarget();
+ }
+
+ @WorkerThread
private void updateGroupKeyIfNecessary(StatusBarNotification sbn) {
String childKey = sbn.getKey();
String oldGroupKey = mNotificationGroupKeyMap.get(childKey);
@@ -328,43 +294,23 @@
}
}
- /** This makes a potentially expensive binder call and should be run on a background thread. */
+ /**
+ * This makes a potentially expensive binder call and should be run on a background thread.
+ */
+ @WorkerThread
public List<StatusBarNotification> getNotificationsForKeys(List<NotificationKeyData> keys) {
- StatusBarNotification[] notifications = NotificationListener.this
- .getActiveNotifications(NotificationKeyData.extractKeysOnly(keys)
- .toArray(new String[keys.size()]));
- return notifications == null
- ? Collections.<StatusBarNotification>emptyList() : Arrays.asList(notifications);
+ StatusBarNotification[] notifications = getActiveNotifications(
+ keys.stream().map(n -> n.notificationKey).toArray(String[]::new));
+ return notifications == null ? Collections.emptyList() : Arrays.asList(notifications);
}
/**
- * Filter out notifications that don't have an intent
- * or are headers for grouped notifications.
- *
- * @see #shouldBeFilteredOut(StatusBarNotification)
+ * Returns true for notifications that don't have an intent
+ * or are headers for grouped notifications and should be filtered out.
*/
- private List<StatusBarNotification> filterNotifications(
- StatusBarNotification[] notifications) {
- if (notifications == null) return null;
- IntSet removedNotifications = new IntSet();
- for (int i = 0; i < notifications.length; i++) {
- if (shouldBeFilteredOut(notifications[i])) {
- removedNotifications.add(i);
- }
- }
- List<StatusBarNotification> filteredNotifications = new ArrayList<>(
- notifications.length - removedNotifications.size());
- for (int i = 0; i < notifications.length; i++) {
- if (!removedNotifications.contains(i)) {
- filteredNotifications.add(notifications[i]);
- }
- }
- return filteredNotifications;
- }
-
+ @WorkerThread
private boolean shouldBeFilteredOut(StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
-
updateGroupKeyIfNecessary(sbn);
getCurrentRanking().getRanking(sbn.getKey(), mTempRanking);
@@ -385,16 +331,16 @@
return (isGroupHeader || missingTitleAndText);
}
+ private static Pair<PackageUserKey, NotificationKeyData> toKeyPair(StatusBarNotification sbn) {
+ return Pair.create(PackageUserKey.fromNotification(sbn),
+ NotificationKeyData.fromNotification(sbn));
+ }
+
public interface NotificationsChangedListener {
void onNotificationPosted(PackageUserKey postedPackageUserKey,
- NotificationKeyData notificationKey, boolean shouldBeFilteredOut);
+ NotificationKeyData notificationKey);
void onNotificationRemoved(PackageUserKey removedPackageUserKey,
NotificationKeyData notificationKey);
void onNotificationFullRefresh(List<StatusBarNotification> activeNotifications);
}
-
- public interface StatusBarNotificationsChangedListener {
- void onNotificationPosted(StatusBarNotification sbn);
- void onNotificationRemoved(StatusBarNotification sbn);
- }
}
diff --git a/src/com/android/launcher3/pm/PinRequestHelper.java b/src/com/android/launcher3/pm/PinRequestHelper.java
index 68ea6c4..e13645c 100644
--- a/src/com/android/launcher3/pm/PinRequestHelper.java
+++ b/src/com/android/launcher3/pm/PinRequestHelper.java
@@ -82,7 +82,7 @@
WorkspaceItemInfo info = new WorkspaceItemInfo(si, context);
// Apply the unbadged icon and fetch the actual icon asynchronously.
LauncherIcons li = LauncherIcons.obtain(context);
- info.applyFrom(li.createShortcutIcon(si, false /* badged */));
+ info.bitmap = li.createShortcutIcon(si, false /* badged */);
li.recycle();
LauncherAppState.getInstance(context).getModel()
.updateAndBindWorkspaceItem(info, si);
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 2034926..79b41c1 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -197,9 +197,6 @@
* @return the container if shown or null.
*/
public static PopupContainerWithArrow showForIcon(BubbleTextView icon) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_CONTEXT_MENU, "showForIcon");
- }
Launcher launcher = Launcher.getLauncher(icon.getContext());
if (getOpen(launcher) != null) {
// There is already an items container open, so don't open this one.
@@ -240,9 +237,6 @@
}
protected void populateAndShow(BubbleTextView icon, ItemInfo item) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_CONTEXT_MENU, "populateAndShow");
- }
PopupDataProvider popupDataProvider = mLauncher.getPopupDataProvider();
populateAndShow(icon,
popupDataProvider.getShortcutCountForItem(item),
@@ -507,7 +501,7 @@
DotInfo dotInfo = mLauncher.getDotInfoForItem(itemInfo);
if (mNotificationItemView != null && dotInfo != null) {
mNotificationItemView.updateHeader(
- dotInfo.getNotificationCount(), itemInfo.iconColor);
+ dotInfo.getNotificationCount(), itemInfo.bitmap.color);
}
}
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index 4612b2a..c5aa836 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -20,13 +20,15 @@
import android.service.notification.StatusBarNotification;
import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.notification.NotificationListener;
-import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.ShortcutUtil;
@@ -39,13 +41,9 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
/**
* Provides data for the popup menu that appears after long-clicking on apps.
*/
@@ -76,28 +74,14 @@
@Override
public void onNotificationPosted(PackageUserKey postedPackageUserKey,
- NotificationKeyData notificationKey, boolean shouldBeFilteredOut) {
+ NotificationKeyData notificationKey) {
DotInfo dotInfo = mPackageUserToDotInfos.get(postedPackageUserKey);
- boolean dotShouldBeRefreshed;
if (dotInfo == null) {
- if (!shouldBeFilteredOut) {
- DotInfo newDotInfo = new DotInfo();
- newDotInfo.addOrUpdateNotificationKey(notificationKey);
- mPackageUserToDotInfos.put(postedPackageUserKey, newDotInfo);
- dotShouldBeRefreshed = true;
- } else {
- dotShouldBeRefreshed = false;
- }
- } else {
- dotShouldBeRefreshed = shouldBeFilteredOut
- ? dotInfo.removeNotificationKey(notificationKey)
- : dotInfo.addOrUpdateNotificationKey(notificationKey);
- if (dotInfo.getNotificationKeys().size() == 0) {
- mPackageUserToDotInfos.remove(postedPackageUserKey);
- }
+ dotInfo = new DotInfo();
+ mPackageUserToDotInfos.put(postedPackageUserKey, dotInfo);
}
- if (dotShouldBeRefreshed) {
- updateNotificationDots(t -> postedPackageUserKey.equals(t));
+ if (dotInfo.addOrUpdateNotificationKey(notificationKey)) {
+ updateNotificationDots(postedPackageUserKey::equals);
}
}
@@ -109,7 +93,7 @@
if (oldDotInfo.getNotificationKeys().size() == 0) {
mPackageUserToDotInfos.remove(removedPackageUserKey);
}
- updateNotificationDots(t -> removedPackageUserKey.equals(t));
+ updateNotificationDots(removedPackageUserKey::equals);
trimNotifications(mPackageUserToDotInfos);
}
}
@@ -195,14 +179,6 @@
: getNotificationsForItem(info, dotInfo.getNotificationKeys());
}
- /** This makes a potentially expensive binder call and should be run on a background thread. */
- public @NonNull List<StatusBarNotification> getStatusBarNotificationsForKeys(
- List<NotificationKeyData> notificationKeys) {
- NotificationListener notificationListener = NotificationListener.getInstanceIfConnected();
- return notificationListener == null ? Collections.EMPTY_LIST
- : notificationListener.getNotificationsForKeys(notificationKeys);
- }
-
public void cancelNotification(String notificationKey) {
NotificationListener notificationListener = NotificationListener.getInstanceIfConnected();
if (notificationListener == null) {
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index dbfe988..80c6683 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -20,7 +20,9 @@
import android.content.pm.ShortcutInfo;
import android.os.Handler;
import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
@@ -28,6 +30,7 @@
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.notification.NotificationInfo;
import com.android.launcher3.notification.NotificationKeyData;
+import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.util.PackageUserKey;
@@ -37,9 +40,7 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
+import java.util.stream.Collectors;
/**
* Contains logic relevant to populating a {@link PopupContainerWithArrow}. In particular,
@@ -130,12 +131,15 @@
final UserHandle user = originalInfo.user;
return () -> {
if (!notificationKeys.isEmpty()) {
- List<StatusBarNotification> notifications = launcher.getPopupDataProvider()
- .getStatusBarNotificationsForKeys(notificationKeys);
- List<NotificationInfo> infos = new ArrayList<>(notifications.size());
- for (int i = 0; i < notifications.size(); i++) {
- StatusBarNotification notification = notifications.get(i);
- infos.add(new NotificationInfo(launcher, notification));
+ NotificationListener notificationListener =
+ NotificationListener.getInstanceIfConnected();
+ final List<NotificationInfo> infos;
+ if (notificationListener == null) {
+ infos = Collections.emptyList();
+ } else {
+ infos = notificationListener.getNotificationsForKeys(notificationKeys).stream()
+ .map(sbn -> new NotificationInfo(launcher, sbn))
+ .collect(Collectors.toList());
}
uiHandler.post(() -> container.applyNotificationInfos(infos));
}
@@ -150,7 +154,7 @@
final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, launcher);
// Use unbadged icon for the menu.
LauncherIcons li = LauncherIcons.obtain(launcher);
- si.applyFrom(li.createShortcutIcon(shortcut, false /* badged */));
+ si.bitmap = li.createShortcutIcon(shortcut, false /* badged */);
li.recycle();
si.rank = i;
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index d0e648f..64df384 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -24,9 +24,10 @@
import android.graphics.Color;
import android.os.Bundle;
import android.os.Debug;
-import android.util.Log;
import android.view.View;
+import androidx.annotation.Keep;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
@@ -177,11 +178,6 @@
}
protected boolean isLauncherInitialized() {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "isLauncherInitialized " + Launcher.ACTIVITY_TRACKER.getCreatedActivity() + ", "
- + LauncherAppState.getInstance(mContext).getModel().isModelLoaded());
- }
return Launcher.ACTIVITY_TRACKER.getCreatedActivity() == null
|| LauncherAppState.getInstance(mContext).getModel().isModelLoaded();
}
@@ -191,6 +187,22 @@
Runtime.getRuntime().runFinalization();
final CountDownLatch fence = new CountDownLatch(1);
+ createFinalizationObserver(fence);
+ try {
+ do {
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().runFinalization();
+ } while (!fence.await(100, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ // Create the observer in the scope of a method to minimize the chance that
+ // it remains live in a DEX/machine register at the point of the fence guard.
+ // This must be kept to avoid R8 inlining it.
+ @Keep
+ private static void createFinalizationObserver(CountDownLatch fence) {
new Object() {
@Override
protected void finalize() throws Throwable {
@@ -201,13 +213,5 @@
}
}
};
- try {
- do {
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- } while (!fence.await(100, TimeUnit.MILLISECONDS));
- } catch (InterruptedException ex) {
- throw new RuntimeException(ex);
- }
}
}
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 923c466..d686e95 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -84,7 +84,5 @@
public static final String NO_BACKGROUND_TO_OVERVIEW_TAG = "b/138251824";
public static final String NO_DRAG_TO_WORKSPACE = "b/138729456";
public static final String APP_NOT_DISABLED = "b/139891609";
- public static final String NO_CONTEXT_MENU = "b/141770616";
- public static final String LAUNCHER_DIDNT_INITIALIZE = "b/142514365";
public static final String CRASH_ADD_CUSTOM_SHORTCUT = "b/141568904";
}
diff --git a/src/com/android/launcher3/touch/ItemLongClickListener.java b/src/com/android/launcher3/touch/ItemLongClickListener.java
index 86d2b39..aa02d0a 100644
--- a/src/com/android/launcher3/touch/ItemLongClickListener.java
+++ b/src/com/android/launcher3/touch/ItemLongClickListener.java
@@ -79,19 +79,10 @@
}
private static boolean onAllAppsItemLongClick(View v) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_CONTEXT_MENU, "onAllAppsItemLongClick1");
- }
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!canStartDrag(launcher)) return false;
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_CONTEXT_MENU, "onAllAppsItemLongClick2");
- }
// When we have exited all apps or are in transition, disregard long clicks
if (!launcher.isInState(ALL_APPS) && !launcher.isInState(OVERVIEW)) return false;
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.NO_CONTEXT_MENU, "onAllAppsItemLongClick3");
- }
if (launcher.getWorkspace().isSwitchingState()) return false;
// Start the drag
diff --git a/src/com/android/launcher3/util/ActivityTracker.java b/src/com/android/launcher3/util/ActivityTracker.java
index b4f361f..4b931f4 100644
--- a/src/com/android/launcher3/util/ActivityTracker.java
+++ b/src/com/android/launcher3/util/ActivityTracker.java
@@ -45,13 +45,7 @@
}
public void onActivityDestroyed(T activity) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, "onActivityDestroyed");
- }
if (mCurrentActivity.get() == activity) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, "onActivityDestroyed: clear");
- }
mCurrentActivity.clear();
}
}
@@ -97,10 +91,6 @@
}
public boolean handleCreate(T activity) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE,
- "ActivityTracker.handleCreate " + mCurrentActivity.get() + " => " + activity);
- }
mCurrentActivity = new WeakReference<>(activity);
return handleIntent(activity, activity.getIntent(), false, false);
}
diff --git a/src/com/android/launcher3/util/ContentWriter.java b/src/com/android/launcher3/util/ContentWriter.java
index 00adf10..2d64353 100644
--- a/src/com/android/launcher3/util/ContentWriter.java
+++ b/src/com/android/launcher3/util/ContentWriter.java
@@ -26,6 +26,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.GraphicsUtils;
/**
@@ -37,7 +38,7 @@
private final Context mContext;
private CommitParams mCommitParams;
- private Bitmap mIcon;
+ private BitmapInfo mIcon;
private UserHandle mUser;
public ContentWriter(Context context, CommitParams commitParams) {
@@ -79,7 +80,7 @@
return this;
}
- public ContentWriter putIcon(Bitmap value, UserHandle user) {
+ public ContentWriter putIcon(BitmapInfo value, UserHandle user) {
mIcon = value;
mUser = user;
return this;
@@ -97,7 +98,7 @@
Preconditions.assertNonUiThread();
if (mIcon != null && !LauncherAppState.getInstance(context).getIconCache()
.isDefaultIcon(mIcon, mUser)) {
- mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(mIcon));
+ mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(mIcon.icon));
mIcon = null;
}
return mValues;
diff --git a/src/com/android/launcher3/util/VibratorWrapper.java b/src/com/android/launcher3/util/VibratorWrapper.java
new file mode 100644
index 0000000..04741a1
--- /dev/null
+++ b/src/com/android/launcher3/util/VibratorWrapper.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 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.util;
+
+import static android.os.VibrationEffect.createPredefined;
+import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.annotation.TargetApi;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Build;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.provider.Settings;
+
+/**
+ * Wrapper around {@link Vibrator} to easily perform haptic feedback where necessary.
+ */
+@TargetApi(Build.VERSION_CODES.Q)
+public class VibratorWrapper {
+
+ public static final MainThreadInitializedObject<VibratorWrapper> INSTANCE =
+ new MainThreadInitializedObject<>(VibratorWrapper::new);
+
+ private static final VibrationEffect EFFECT_CLICK =
+ createPredefined(VibrationEffect.EFFECT_CLICK);
+
+ /**
+ * Haptic when entering overview.
+ */
+ public static final VibrationEffect OVERVIEW_HAPTIC = EFFECT_CLICK;
+
+ private final Vibrator mVibrator;
+ private final boolean mHasVibrator;
+
+ private boolean mIsHapticFeedbackEnabled;
+
+ public VibratorWrapper(Context context) {
+ mVibrator = context.getSystemService(Vibrator.class);
+ mHasVibrator = mVibrator.hasVibrator();
+ if (mHasVibrator) {
+ final ContentResolver resolver = context.getContentResolver();
+ mIsHapticFeedbackEnabled = isHapticFeedbackEnabled(resolver);
+ final ContentObserver observer = new ContentObserver(MAIN_EXECUTOR.getHandler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mIsHapticFeedbackEnabled = isHapticFeedbackEnabled(resolver);
+ }
+ };
+ resolver.registerContentObserver(Settings.System.getUriFor(HAPTIC_FEEDBACK_ENABLED),
+ false /* notifyForDescendents */, observer);
+ } else {
+ mIsHapticFeedbackEnabled = false;
+ }
+ }
+
+ private boolean isHapticFeedbackEnabled(ContentResolver resolver) {
+ return Settings.System.getInt(resolver, HAPTIC_FEEDBACK_ENABLED, 0) == 1;
+ }
+
+ /** Vibrates with the given effect if haptic feedback is available and enabled. */
+ public void vibrate(VibrationEffect vibrationEffect) {
+ if (mHasVibrator && mIsHapticFeedbackEnabled) {
+ UI_HELPER_EXECUTOR.execute(() -> mVibrator.vibrate(vibrationEffect));
+ }
+ }
+}
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 2a4c5a7..e43fc8a 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -170,10 +170,8 @@
// Only look for controllers if we are not dispatching from gesture area and proxy is
// not active
mActiveController = findControllerToHandleTouch(ev);
-
- if (mActiveController != null) return true;
}
- return false;
+ return mActiveController != null;
}
@Override
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 50db40f..3ece5f4 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -33,12 +33,12 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.R;
import com.android.launcher3.graphics.DrawableFactory;
+import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Themes;
@@ -128,7 +128,7 @@
mCenterDrawable.setCallback(null);
mCenterDrawable = null;
}
- if (info.iconBitmap != null) {
+ if (info.bitmap.icon != null) {
// The view displays three modes,
// 1) App icon in the center
// 2) Preload icon in the center
@@ -142,7 +142,7 @@
} else if (isReadyForClickSetup()) {
mCenterDrawable = drawableFactory.newIcon(getContext(), info);
mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate();
- updateSettingColor(info.iconColor);
+ updateSettingColor(info.bitmap.color);
} else {
mCenterDrawable = DrawableFactory.INSTANCE.get(getContext())
.newPendingIcon(getContext(), info);
diff --git a/src/com/android/launcher3/widget/WidgetsDiffReporter.java b/src/com/android/launcher3/widget/WidgetsDiffReporter.java
index 435125b..f3b325d 100644
--- a/src/com/android/launcher3/widget/WidgetsDiffReporter.java
+++ b/src/com/android/launcher3/widget/WidgetsDiffReporter.java
@@ -18,6 +18,8 @@
import android.util.Log;
+import androidx.recyclerview.widget.RecyclerView;
+
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.widget.WidgetsListAdapter.WidgetListRowEntryComparator;
@@ -25,8 +27,6 @@
import java.util.ArrayList;
import java.util.Iterator;
-import androidx.recyclerview.widget.RecyclerView;
-
/**
* Do diff on widget's tray list items and call the {@link RecyclerView.Adapter}
* methods accordingly.
@@ -137,7 +137,7 @@
}
private boolean isSamePackageItemInfo(PackageItemInfo curInfo, PackageItemInfo newInfo) {
- return curInfo.iconBitmap.equals(newInfo.iconBitmap) &&
- !mIconCache.isDefaultIcon(curInfo.iconBitmap, curInfo.user);
+ return curInfo.bitmap.icon.equals(newInfo.bitmap.icon)
+ && !mIconCache.isDefaultIcon(curInfo.bitmap, curInfo.user);
}
}
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 7029ad5..0dcfaa8 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -142,7 +142,7 @@
when(mMockIconCache.getDefaultIcon(eq(mLoaderCursor.user)))
.thenReturn(BitmapInfo.fromBitmap(icon));
WorkspaceItemInfo info = mLoaderCursor.loadSimpleWorkspaceItem();
- assertEquals(icon, info.iconBitmap);
+ assertEquals(icon, info.bitmap.icon);
assertEquals("my-shortcut", info.title);
assertEquals(ITEM_TYPE_SHORTCUT, info.itemType);
}
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 1c17e34..259f9ed 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -48,7 +48,6 @@
@Test
@PortraitLandscape
- @Stability(flavors = UNBUNDLED_POSTSUBMIT) // b/142514365
public void testDragIcon() throws Throwable {
clearHomescreen();
mDevice.pressHome();
diff --git a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
index 08fa098..858cb38 100644
--- a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
+++ b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java
@@ -21,6 +21,7 @@
import android.os.Build;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import org.junit.rules.TestRule;
@@ -86,6 +87,19 @@
}
private static int getRunFlavor() {
+ final String flavorOverride = InstrumentationRegistry.getArguments().getString("flavor");
+
+ if (flavorOverride != null) {
+ Log.d(TAG, "Flavor override: " + flavorOverride);
+ try {
+ return (int) TestStabilityRule.class.getField(flavorOverride).get(null);
+ } catch (NoSuchFieldException e) {
+ throw new AssertionError("Unrecognized run flavor override: " + flavorOverride);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
final String launcherVersion;
try {
launcherVersion = getInstrumentation().
diff --git a/tests/src/com/android/launcher3/widget/WidgetsListAdapterTest.java b/tests/src/com/android/launcher3/widget/WidgetsListAdapterTest.java
index a31d8a6..c7f7cd6 100644
--- a/tests/src/com/android/launcher3/widget/WidgetsListAdapterTest.java
+++ b/tests/src/com/android/launcher3/widget/WidgetsListAdapterTest.java
@@ -23,16 +23,19 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.graphics.Bitmap;
+import android.view.LayoutInflater;
+
+import androidx.recyclerview.widget.RecyclerView;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import android.view.LayoutInflater;
-import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.compat.AppWidgetManagerCompat;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.util.MultiHashMap;
@@ -46,8 +49,6 @@
import java.util.ArrayList;
import java.util.Map;
-import androidx.recyclerview.widget.RecyclerView;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class WidgetsListAdapterTest {
@@ -136,7 +137,7 @@
PackageItemInfo pInfo = new PackageItemInfo(wi.componentName.getPackageName());
pInfo.title = pInfo.packageName;
pInfo.user = wi.user;
- pInfo.iconBitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8);
+ pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
newMap.addToList(pInfo, wi);
if (newMap.size() == num) {
break;