Merge changes from topic "am-01ff3d34-0eea-44d5-99f7-af2df518afb2" into ub-launcher3-master
* changes:
[automerger] Fix bug where labels were visible in hotseat / invisible in workspace. am: f1eae802b5
Fix bug where labels were visible in hotseat / invisible in workspace.
diff --git a/res/layout/gradient_bg.xml b/res/layout/gradient_bg.xml
index db448d7..6c6626c 100644
--- a/res/layout/gradient_bg.xml
+++ b/res/layout/gradient_bg.xml
@@ -20,5 +20,4 @@
android:id="@+id/gradient_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:visibility="gone"
launcher:layout_ignoreInsets="true" />
\ No newline at end of file
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 485125e..cd72fba 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -42,6 +42,7 @@
import com.android.launcher3.IconCache.IconLoadRequest;
import com.android.launcher3.IconCache.ItemInfoUpdateReceiver;
+import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.folder.FolderIcon;
@@ -59,7 +60,7 @@
* because we want to make the bubble taller than the text and TextView's clip is
* too aggressive.
*/
-public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
+public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback {
private static final int DISPLAY_WORKSPACE = 0;
private static final int DISPLAY_ALL_APPS = 1;
@@ -330,6 +331,13 @@
refreshDrawableState();
}
+ @Override
+ public void onLauncherResume() {
+ // Reset the pressed state of icon that was locked in the press state while activity
+ // was launching
+ setStayPressed(false);
+ }
+
void clearPressedBackground() {
setPressed(false);
setStayPressed(false);
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 3759300..ffc2b02 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -215,7 +215,7 @@
* On drop animate the dropView to the icon.
*/
@Override
- public void onDrop(final DragObject d) {
+ public void onDrop(final DragObject d, final DragOptions options) {
final DragLayer dragLayer = mLauncher.getDragLayer();
final Rect from = new Rect();
dragLayer.getViewRectRelativeToSelf(d.dragView, from);
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index 7d047d7..2307b89 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -19,6 +19,7 @@
import android.graphics.Rect;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
/**
@@ -106,7 +107,7 @@
/**
* Handle an object being dropped on the DropTarget
*/
- void onDrop(DragObject dragObject);
+ void onDrop(DragObject dragObject, DragOptions options);
void onDragEnter(DragObject dragObject);
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index eb6a704..f78cde5 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -49,28 +49,29 @@
}
@Override
- public void completeDrop(DragObject d) {
- DropTargetResultCallback callback = d.dragSource instanceof DropTargetResultCallback
- ? (DropTargetResultCallback) d.dragSource : null;
- startDetailsActivityForInfo(d.dragInfo, mLauncher, callback);
+ protected ComponentName performDropAction(DragObject d) {
+ return performDropAction(mLauncher, d.dragInfo, null, null);
}
/**
* @return Whether the activity was started.
*/
public static boolean startDetailsActivityForInfo(
- ItemInfo info, Launcher launcher, DropTargetResultCallback callback) {
- return startDetailsActivityForInfo(info, launcher, callback, null, null);
+ ItemInfo info, Launcher launcher, Rect sourceBounds, Bundle opts) {
+ return performDropAction(launcher, info, sourceBounds, opts) != null;
}
- public static boolean startDetailsActivityForInfo(ItemInfo info, Launcher launcher,
- DropTargetResultCallback callback, Rect sourceBounds, Bundle opts) {
+ /**
+ * Performs the drop action and returns the target component for the dragObject or null if
+ * the action was not performed.
+ */
+ private static ComponentName performDropAction(Context context, ItemInfo info,
+ Rect sourceBounds, Bundle opts) {
if (info instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
- launcher.startActivity(promiseAppInfo.getMarketIntent());
- return true;
+ context.startActivity(promiseAppInfo.getMarketIntent());
+ return null;
}
- boolean result = false;
ComponentName componentName = null;
if (info instanceof AppInfo) {
componentName = ((AppInfo) info).componentName;
@@ -83,19 +84,15 @@
}
if (componentName != null) {
try {
- LauncherAppsCompat.getInstance(launcher)
+ LauncherAppsCompat.getInstance(context)
.showAppDetailsForProfile(componentName, info.user, sourceBounds, opts);
- result = true;
+ return componentName;
} catch (SecurityException | ActivityNotFoundException e) {
- Toast.makeText(launcher, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+ Toast.makeText(context, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch settings", e);
}
}
-
- if (callback != null) {
- sendUninstallResult(launcher, result, componentName, info.user, callback);
- }
- return result;
+ return null;
}
@Override
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 0370777..df1eec6 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -27,7 +27,9 @@
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.os.Handler;
import android.os.Looper;
+import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
import android.os.UserHandle;
@@ -61,6 +63,9 @@
public class InstallShortcutReceiver extends BroadcastReceiver {
+ private static final int MSG_ADD_TO_QUEUE = 1;
+ private static final int MSG_FLUSH_QUEUE = 2;
+
public static final int FLAG_ACTIVITY_PAUSED = 1;
public static final int FLAG_LOADER_RUNNING = 2;
public static final int FLAG_DRAG_AND_DROP = 4;
@@ -93,73 +98,98 @@
public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;
- private static final Object sLock = new Object();
+ private static final Handler sHandler = new Handler(LauncherModel.getWorkerLooper()) {
- private static void addToInstallQueue(
- SharedPreferences sharedPrefs, PendingInstallShortcutInfo info) {
- synchronized(sLock) {
- String encoded = info.encodeToString();
- if (encoded != null) {
- Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
- strings = (strings != null) ? new HashSet<>(strings) : new HashSet<String>(1);
- strings.add(encoded);
- sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ADD_TO_QUEUE: {
+ Pair<Context, PendingInstallShortcutInfo> pair =
+ (Pair<Context, PendingInstallShortcutInfo>) msg.obj;
+ String encoded = pair.second.encodeToString();
+ SharedPreferences prefs = Utilities.getPrefs(pair.first);
+ Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
+ strings = (strings != null) ? new HashSet<>(strings) : new HashSet<String>(1);
+ strings.add(encoded);
+ prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
+ return;
+ }
+ case MSG_FLUSH_QUEUE: {
+ Context context = (Context) msg.obj;
+ LauncherModel model = LauncherAppState.getInstance(context).getModel();
+ if (model.getCallback() == null) {
+ // Launcher not loaded
+ return;
+ }
+
+ ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
+ SharedPreferences prefs = Utilities.getPrefs(context);
+ Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
+ if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
+ if (strings == null) {
+ return;
+ }
+
+ LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+ for (String encoded : strings) {
+ PendingInstallShortcutInfo info = decode(encoded, context);
+ if (info == null) {
+ continue;
+ }
+
+ String pkg = getIntentPackage(info.launchIntent);
+ if (!TextUtils.isEmpty(pkg)
+ && !launcherApps.isPackageEnabledForProfile(pkg, info.user)) {
+ if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
+ + info.launchIntent);
+ continue;
+ }
+
+ // Generate a shortcut info to add into the model
+ installQueue.add(info.getItemInfo());
+ }
+ prefs.edit().remove(APPS_PENDING_INSTALL).apply();
+ if (!installQueue.isEmpty()) {
+ model.addAndBindAddedWorkspaceItems(installQueue);
+ }
+ return;
+ }
}
}
- }
+ };
public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
UserHandle user) {
if (packageNames.isEmpty()) {
return;
}
+ Preconditions.assertWorkerThread();
+
SharedPreferences sp = Utilities.getPrefs(context);
- synchronized(sLock) {
- Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
- if (DBG) {
- Log.d(TAG, "APPS_PENDING_INSTALL: " + strings
- + ", removing packages: " + packageNames);
- }
- if (Utilities.isEmpty(strings)) {
- return;
- }
- Set<String> newStrings = new HashSet<>(strings);
- Iterator<String> newStringsIter = newStrings.iterator();
- while (newStringsIter.hasNext()) {
- String encoded = newStringsIter.next();
- try {
- Decoder decoder = new Decoder(encoded, context);
- if (packageNames.contains(getIntentPackage(decoder.launcherIntent)) &&
- user.equals(decoder.user)) {
- newStringsIter.remove();
- }
- } catch (JSONException | URISyntaxException e) {
- Log.d(TAG, "Exception reading shortcut to add: " + e);
+ Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
+ if (DBG) {
+ Log.d(TAG, "APPS_PENDING_INSTALL: " + strings
+ + ", removing packages: " + packageNames);
+ }
+ if (Utilities.isEmpty(strings)) {
+ return;
+ }
+ Set<String> newStrings = new HashSet<>(strings);
+ Iterator<String> newStringsIter = newStrings.iterator();
+ while (newStringsIter.hasNext()) {
+ String encoded = newStringsIter.next();
+ try {
+ Decoder decoder = new Decoder(encoded, context);
+ if (packageNames.contains(getIntentPackage(decoder.launcherIntent)) &&
+ user.equals(decoder.user)) {
newStringsIter.remove();
}
+ } catch (JSONException | URISyntaxException e) {
+ Log.d(TAG, "Exception reading shortcut to add: " + e);
+ newStringsIter.remove();
}
- sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
}
- }
-
- private static ArrayList<PendingInstallShortcutInfo> getAndClearInstallQueue(Context context) {
- SharedPreferences sharedPrefs = Utilities.getPrefs(context);
- synchronized(sLock) {
- ArrayList<PendingInstallShortcutInfo> infos = new ArrayList<>();
- Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
- if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
- if (strings == null) {
- return infos;
- }
- for (String encoded : strings) {
- PendingInstallShortcutInfo info = decode(encoded, context);
- if (info != null) {
- infos.add(info);
- }
- }
- sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet<String>()).apply();
- return infos;
- }
+ sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
}
public void onReceive(Context context, Intent data) {
@@ -256,7 +286,7 @@
private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
// Queue the item up for adding if launcher has not loaded properly yet
- addToInstallQueue(Utilities.getPrefs(context), info);
+ Message.obtain(sHandler, MSG_ADD_TO_QUEUE, Pair.create(context, info)).sendToTarget();
flushInstallQueue(context);
}
@@ -269,17 +299,10 @@
}
static void flushInstallQueue(Context context) {
- LauncherModel model = LauncherAppState.getInstance(context).getModel();
- boolean launcherNotLoaded = model.getCallback() == null;
- if (sInstallQueueDisabledFlags != 0 || launcherNotLoaded) {
+ if (sInstallQueueDisabledFlags != 0) {
return;
}
-
- ArrayList<PendingInstallShortcutInfo> items = getAndClearInstallQueue(context);
- if (!items.isEmpty()) {
- model.addAndBindAddedWorkspaceItems(
- new LazyShortcutsProvider(context.getApplicationContext(), items));
- }
+ Message.obtain(sHandler, MSG_FLUSH_QUEUE, context.getApplicationContext()).sendToTarget();
}
/**
@@ -601,42 +624,6 @@
return new PendingInstallShortcutInfo(info, original.mContext);
}
- private static class LazyShortcutsProvider extends Provider<List<Pair<ItemInfo, Object>>> {
-
- private final Context mContext;
- private final ArrayList<PendingInstallShortcutInfo> mPendingItems;
-
- public LazyShortcutsProvider(Context context, ArrayList<PendingInstallShortcutInfo> items) {
- mContext = context;
- mPendingItems = items;
- }
-
- /**
- * This must be called on the background thread as this requires multiple calls to
- * packageManager and icon cache.
- */
- @Override
- public ArrayList<Pair<ItemInfo, Object>> get() {
- Preconditions.assertNonUiThread();
- ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
- LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
- for (PendingInstallShortcutInfo pendingInfo : mPendingItems) {
- // If the intent specifies a package, make sure the package exists
- String packageName = getIntentPackage(pendingInfo.launchIntent);
- if (!TextUtils.isEmpty(packageName) && !launcherApps.isPackageEnabledForProfile(
- packageName, pendingInfo.user)) {
- if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
- + pendingInfo.launchIntent);
- continue;
- }
-
- // Generate a shortcut info to add into the model
- installQueue.add(pendingInfo.getItemInfo());
- }
- return installQueue;
- }
- }
-
private static ShortcutInfo createShortcutInfo(Intent data, LauncherAppState app) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ba31926..2945b22 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -119,7 +119,6 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.util.ActivityResultInfo;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.ComponentKeyMapper;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
@@ -203,7 +202,7 @@
static final String APPS_VIEW_SHOWN = "launcher.apps_view_shown";
/** The different states that Launcher can be in. */
- enum State { NONE, WORKSPACE, WORKSPACE_SPRING_LOADED, APPS, APPS_SPRING_LOADED,
+ enum State { WORKSPACE, WORKSPACE_SPRING_LOADED, APPS, APPS_SPRING_LOADED,
WIDGETS, WIDGETS_SPRING_LOADED }
@Thunk State mState = State.WORKSPACE;
@@ -250,11 +249,6 @@
// that results in widgets being inflated in the wrong orientation.
private int mOrientation;
- // We set the state in both onCreate and then onNewIntent in some cases, which causes both
- // scroll issues (because the workspace may not have been measured yet) and extra work.
- // Instead, just save the state that we need to restore Launcher to, and commit it in onResume.
- private State mOnResumeState = State.NONE;
-
private SpannableStringBuilder mDefaultKeySsb = null;
@Thunk boolean mWorkspaceLoading = true;
@@ -263,7 +257,8 @@
private boolean mOnResumeNeedsLoad;
private final ArrayList<Runnable> mBindOnResumeCallbacks = new ArrayList<>();
- private final ArrayList<Runnable> mOnResumeCallbacks = new ArrayList<>();
+ private OnResumeCallback mOnResumeCallback;
+
private ViewOnDrawExecutor mPendingExecutor;
private LauncherModel mModel;
@@ -288,11 +283,6 @@
// it from the context.
private SharedPreferences mSharedPrefs;
- // This is set to the view that launched the activity that navigated the user away from
- // launcher. Since there is no callback for when the activity has finished launching, enable
- // the press state and keep this reference to reset the press state when we return to launcher.
- private BubbleTextView mWaitingForResume;
-
// Exiting spring loaded mode happens with a delay. This runnable object triggers the
// state transition. If another state transition happened during this delay,
// simply unregister this runnable.
@@ -484,13 +474,6 @@
private LauncherCallbacks mLauncherCallbacks;
- public void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onPostCreate(savedInstanceState);
- }
- }
-
public void onInsetsChanged(Rect insets) {
mDeviceProfile.updateInsets(insets);
mDeviceProfile.layout(this, true /* notifyListeners */);
@@ -855,24 +838,10 @@
@Override
protected void onResume() {
TraceHelper.beginSection("ON_RESUME");
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.preOnResume();
- }
super.onResume();
TraceHelper.partitionSection("ON_RESUME", "superCall");
getUserEventDispatcher().resetElapsedSessionMillis();
-
- // Restore the previous launcher state
- if (mOnResumeState == State.WORKSPACE) {
- showWorkspace(false);
- } else if (mOnResumeState == State.APPS) {
- showAppsView(false /* animated */);
- } else if (mOnResumeState == State.WIDGETS) {
- showWidgetsView(false, false);
- }
- mOnResumeState = State.NONE;
-
mPaused = false;
if (mOnResumeNeedsLoad) {
setWorkspaceLoading(true);
@@ -887,22 +856,8 @@
}
mBindOnResumeCallbacks.clear();
}
- if (mOnResumeCallbacks.size() > 0) {
- for (int i = 0; i < mOnResumeCallbacks.size(); i++) {
- mOnResumeCallbacks.get(i).run();
- }
- mOnResumeCallbacks.clear();
- }
- // Reset the pressed state of icons that were locked in the press state while activities
- // were launching
- if (mWaitingForResume != null) {
- // Resets the previous workspace icon press state
- mWaitingForResume.setStayPressed(false);
- }
-
- updateInteraction(Workspace.State.NORMAL, mWorkspace.getState());
-
+ setOnResumeCallback(null);
// Process any items that were added while Launcher was away.
InstallShortcutReceiver.disableAndFlushInstallQueue(
InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED, this);
@@ -1086,8 +1041,10 @@
State[] stateValues = State.values();
State state = (stateOrdinal >= 0 && stateOrdinal < stateValues.length)
? stateValues[stateOrdinal] : State.WORKSPACE;
- if (state == State.APPS || state == State.WIDGETS) {
- mOnResumeState = state;
+ if (state == State.APPS) {
+ showAppsView(false /* animated */);
+ } else if (state == State.WIDGETS) {
+ showWidgetsView(false, false);
}
PendingRequestArgs requestArgs = savedState.getParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS);
@@ -1499,15 +1456,7 @@
// In all these cases, only animate if we're already on home
AbstractFloatingView.closeAllOpenViews(this, alreadyOnHome);
- exitSpringLoadedDragMode();
-
- // If we are already on home, then just animate back to the workspace,
- // otherwise, just wait until onResume to set the state back to Workspace
- if (alreadyOnHome) {
- showWorkspace(true);
- } else {
- mOnResumeState = State.WORKSPACE;
- }
+ showWorkspace(alreadyOnHome /* animated */);
final View v = getWindow().peekDecorView();
if (v != null && v.getWindowToken() != null) {
@@ -1538,11 +1487,7 @@
// as slow logic in the callbacks eat into the time the scroller expects for the snapToPage
// animation.
if (isActionMain) {
- boolean callbackAllowsMoveToDefaultScreen =
- mLauncherCallbacks == null || mLauncherCallbacks
- .shouldMoveToDefaultScreenOnHomeIntent();
- if (shouldMoveToDefaultScreen && !mWorkspace.isTouchActive()
- && callbackAllowsMoveToDefaultScreen) {
+ if (shouldMoveToDefaultScreen && !mWorkspace.isTouchActive()) {
mWorkspace.post(new Runnable() {
@Override
@@ -1749,25 +1694,11 @@
}
private void setWorkspaceLoading(boolean value) {
- boolean isLocked = isWorkspaceLocked();
mWorkspaceLoading = value;
- if (isLocked != isWorkspaceLocked()) {
- onWorkspaceLockedChanged();
- }
}
public void setWaitingForResult(PendingRequestArgs args) {
- boolean isLocked = isWorkspaceLocked();
mPendingRequestArgs = args;
- if (isLocked != isWorkspaceLocked()) {
- onWorkspaceLockedChanged();
- }
- }
-
- protected void onWorkspaceLockedChanged() {
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onWorkspaceLockedChanged();
- }
}
void addAppWidgetFromDropImpl(int appWidgetId, ItemInfo info, AppWidgetHostView boundWidget,
@@ -2127,11 +2058,7 @@
private void startMarketIntentForPackage(View v, String packageName) {
ItemInfo item = (ItemInfo) v.getTag();
Intent intent = PackageManagerHelper.getMarketIntent(packageName);
- boolean success = startActivitySafely(v, intent, item);
- if (success && v instanceof BubbleTextView) {
- mWaitingForResume = (BubbleTextView) v;
- mWaitingForResume.setStayPressed(true);
- }
+ startActivitySafely(v, intent, item);
}
/**
@@ -2201,13 +2128,8 @@
if (intent == null) {
throw new IllegalArgumentException("Input must have a valid intent");
}
- boolean success = startActivitySafely(v, intent, item);
+ startActivitySafely(v, intent, item);
getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115
-
- if (success && v instanceof BubbleTextView) {
- mWaitingForResume = (BubbleTextView) v;
- mWaitingForResume.setStayPressed(true);
- }
}
/**
@@ -2292,44 +2214,6 @@
mDragLayer.onAccessibilityStateChanged(enabled);
}
- /**
- * Called when the user stops interacting with the launcher.
- * This implies that the user is now on the homescreen and is not doing housekeeping.
- */
- protected void onInteractionEnd() {
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onInteractionEnd();
- }
- }
-
- /**
- * Called when the user starts interacting with the launcher.
- * The possible interactions are:
- * - open all apps
- * - reorder an app shortcut, or a widget
- * - open the overview mode.
- * This is a good time to stop doing things that only make sense
- * when the user is on the homescreen and not doing housekeeping.
- */
- protected void onInteractionBegin() {
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onInteractionBegin();
- }
- }
-
- /** Updates the interaction state. */
- public void updateInteraction(Workspace.State fromState, Workspace.State toState) {
- // Only update the interacting state if we are transitioning to/from a view with an
- // overlay
- boolean fromStateWithOverlay = fromState != Workspace.State.NORMAL;
- boolean toStateWithOverlay = toState != Workspace.State.NORMAL;
- if (toStateWithOverlay) {
- onInteractionBegin();
- } else if (fromStateWithOverlay) {
- onInteractionEnd();
- }
- }
-
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
try {
StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
@@ -2438,6 +2322,16 @@
LauncherAppsCompat.getInstance(this).startActivityForProfile(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
+
+ if (v instanceof BubbleTextView) {
+ // This is set to the view that launched the activity that navigated the user away
+ // from launcher. Since there is no callback for when the activity has finished
+ // launching, enable the press state and keep this reference to reset the press
+ // state when we return to launcher.
+ BubbleTextView btv = (BubbleTextView) v;
+ btv.setStayPressed(true);
+ setOnResumeCallback(btv);
+ }
return true;
} catch (ActivityNotFoundException|SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
@@ -2551,11 +2445,11 @@
}
public boolean isAppsViewVisible() {
- return (mState == State.APPS) || (mOnResumeState == State.APPS);
+ return mState == State.APPS;
}
public boolean isWidgetsViewVisible() {
- return (mState == State.WIDGETS) || (mOnResumeState == State.WIDGETS);
+ return mState == State.WIDGETS;
}
@Override
@@ -2720,18 +2614,6 @@
return true;
}
- /**
- * Updates the workspace and interaction state on state change, and return the animation to this
- * new state.
- */
- public Animator startWorkspaceStateChangeAnimation(Workspace.State toState,
- boolean animated, AnimationLayerSet layerViews) {
- Workspace.State fromState = mWorkspace.getState();
- Animator anim = mWorkspace.setStateWithAnimation(toState, animated, layerViews);
- updateInteraction(fromState, toState);
- return anim;
- }
-
public void enterSpringLoadedDragMode() {
if (LOGD) Log.d(TAG, String.format("enterSpringLoadedDragMode [mState=%s", mState.name()));
if (isStateSpringLoaded()) {
@@ -2831,8 +2713,11 @@
}
}
- public void addOnResumeCallback(Runnable run) {
- mOnResumeCallbacks.add(run);
+ public void setOnResumeCallback(OnResumeCallback callback) {
+ if (mOnResumeCallback != null) {
+ mOnResumeCallback.onLauncherResume();
+ }
+ mOnResumeCallback = callback;
}
/**
@@ -3307,10 +3192,6 @@
InstallShortcutReceiver.FLAG_LOADER_RUNNING, this);
NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
-
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.finishBindingItems(false);
- }
TraceHelper.endSection("finishBindingItems");
}
@@ -3710,4 +3591,12 @@
}
}
}
+
+ /**
+ * Callback for listening for onResume
+ */
+ public interface OnResumeCallback {
+
+ void onLauncherResume();
+ }
}
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index 2c9a23f..78d753a 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -39,14 +39,12 @@
*/
void preOnCreate();
void onCreate(Bundle savedInstanceState);
- void preOnResume();
void onResume();
void onStart();
void onStop();
void onPause();
void onDestroy();
void onSaveInstanceState(Bundle outState);
- void onPostCreate(Bundle savedInstanceState);
void onNewIntent(Intent intent);
void onActivityResult(int requestCode, int resultCode, Intent data);
void onRequestPermissionsResult(int requestCode, String[] permissions,
@@ -64,13 +62,7 @@
* Extension points for providing custom behavior on certain user interactions.
*/
void onLauncherProviderChange();
- void finishBindingItems(final boolean upgradePath);
void bindAllApplications(ArrayList<AppInfo> apps);
- void onInteractionBegin();
- void onInteractionEnd();
-
- @Deprecated
- void onWorkspaceLockedChanged();
/**
* Starts a search with {@param initialQuery}. Return false if search was not started.
@@ -81,6 +73,5 @@
/*
* Extensions points for adding / replacing some other aspects of the Launcher experience.
*/
- boolean shouldMoveToDefaultScreenOnHomeIntent();
boolean hasSettings();
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 74a5bac..3e22366 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -192,9 +192,8 @@
/**
* Adds the provided items to the workspace.
*/
- public void addAndBindAddedWorkspaceItems(
- Provider<List<Pair<ItemInfo, Object>>> appsProvider) {
- enqueueModelUpdateTask(new AddWorkspaceItemsTask(appsProvider));
+ public void addAndBindAddedWorkspaceItems(List<Pair<ItemInfo, Object>> itemList) {
+ enqueueModelUpdateTask(new AddWorkspaceItemsTask(itemList));
}
public ModelWriter getWriter(boolean hasVerticalHotseat) {
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index e247490..be0ed0c 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -361,8 +361,8 @@
AnimationLayerSet layerViews) {
// Create the workspace animation.
// NOTE: this call apparently also sets the state for the workspace if !animated
- Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState,
- animated, layerViews);
+ Animator workspaceAnim = mLauncher.getWorkspace().
+ setStateWithAnimation(toWorkspaceState, animated, layerViews);
if (animated && initialized) {
// Play the workspace animation
diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java
index 3f7de06..e8c4528 100644
--- a/src/com/android/launcher3/UninstallDropTarget.java
+++ b/src/com/android/launcher3/UninstallDropTarget.java
@@ -12,9 +12,13 @@
import android.os.UserManager;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.View;
import android.widget.Toast;
+import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import java.net.URISyntaxException;
@@ -91,98 +95,110 @@
}
@Override
- public void onDrop(DragObject d) {
- // Differ item deletion
- if (d.dragSource instanceof DropTargetSource) {
- ((DropTargetSource) d.dragSource).deferCompleteDropAfterUninstallActivity();
+ public void onDrop(DragObject d, DragOptions options) {
+ // Defer onComplete
+ if (options.deferCompleteForUninstall) {
+ d.dragSource = new DeferredOnComplete(d.dragSource, getContext());
}
- super.onDrop(d);
+ super.onDrop(d, options);
}
@Override
public void completeDrop(final DragObject d) {
- DropTargetResultCallback callback = d.dragSource instanceof DropTargetResultCallback
- ? (DropTargetResultCallback) d.dragSource : null;
- startUninstallActivity(mLauncher, d.dragInfo, callback);
+ ComponentName target = performDropAction(d);
+ if (d.dragSource instanceof DeferredOnComplete) {
+ DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource;
+ if (target != null) {
+ deferred.mPackageName = target.getPackageName();
+ mLauncher.setOnResumeCallback(deferred);
+ } else {
+ deferred.sendFailure();
+ }
+ }
}
- public static boolean startUninstallActivity(Launcher launcher, ItemInfo info) {
- return startUninstallActivity(launcher, info, null);
+ /**
+ * Performs the drop action and returns the target component for the dragObject or null if
+ * the action was not performed.
+ */
+ protected ComponentName performDropAction(DragObject d) {
+ return performDropAction(mLauncher, d.dragInfo);
}
- public static boolean startUninstallActivity(
- final Launcher launcher, ItemInfo info, DropTargetResultCallback callback) {
- final ComponentName cn = getUninstallTarget(launcher, info);
-
- boolean canUninstall;
+ /**
+ * Performs the drop action and returns the target component for the dragObject or null if
+ * the action was not performed.
+ */
+ private static ComponentName performDropAction(Context context, ItemInfo info) {
+ ComponentName cn = getUninstallTarget(context, info);
if (cn == null) {
// System applications cannot be installed. For now, show a toast explaining that.
// We may give them the option of disabling apps this way.
- Toast.makeText(launcher, R.string.uninstall_system_app_text, Toast.LENGTH_SHORT).show();
- canUninstall = false;
- } else {
- try {
- Intent i = Intent.parseUri(launcher.getString(R.string.delete_package_intent), 0)
- .setData(Uri.fromParts("package", cn.getPackageName(), cn.getClassName()))
- .putExtra(Intent.EXTRA_USER, info.user);
- launcher.startActivity(i);
- canUninstall = true;
- } catch (URISyntaxException e) {
- Log.e(TAG, "Failed to parse intent to start uninstall activity for item=" + info);
- canUninstall = false;
+ Toast.makeText(context, R.string.uninstall_system_app_text, Toast.LENGTH_SHORT).show();
+ return null;
+ }
+ try {
+ Intent i = Intent.parseUri(context.getString(R.string.delete_package_intent), 0)
+ .setData(Uri.fromParts("package", cn.getPackageName(), cn.getClassName()))
+ .putExtra(Intent.EXTRA_USER, info.user);
+ context.startActivity(i);
+ return cn;
+ } catch (URISyntaxException e) {
+ Log.e(TAG, "Failed to parse intent to start uninstall activity for item=" + info);
+ return null;
+ }
+ }
+
+ public static boolean startUninstallActivity(Launcher launcher, ItemInfo info) {
+ return performDropAction(launcher, info) != null;
+ }
+
+ /**
+ * A wrapper around {@link DragSource} which delays the {@link #onDropCompleted} action until
+ * {@link #onLauncherResume}
+ */
+ private class DeferredOnComplete implements DragSource, OnResumeCallback {
+
+ private final DragSource mOriginal;
+ private final Context mContext;
+
+ private String mPackageName;
+ private DragObject mDragObject;
+
+ public DeferredOnComplete(DragSource original, Context context) {
+ mOriginal = original;
+ mContext = context;
+ }
+
+ @Override
+ public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
+ boolean success) {
+ mDragObject = d;
+ }
+
+ @Override
+ public void fillInLogContainerData(View v, ItemInfo info, Target target,
+ Target targetParent) {
+ mOriginal.fillInLogContainerData(v, info, target, targetParent);
+ }
+
+ @Override
+ public void onLauncherResume() {
+ // We use MATCH_UNINSTALLED_PACKAGES as the app can be on SD card as well.
+ if (LauncherAppsCompat.getInstance(mContext)
+ .getApplicationInfo(mPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES,
+ mDragObject.dragInfo.user) == null) {
+ mDragObject.dragSource = mOriginal;
+ mOriginal.onDropCompleted(UninstallDropTarget.this, mDragObject, false, true);
+ } else {
+ sendFailure();
}
}
- if (callback != null) {
- sendUninstallResult(launcher, canUninstall, cn, info.user, callback);
+
+ public void sendFailure() {
+ mDragObject.dragSource = mOriginal;
+ mDragObject.cancelled = true;
+ mOriginal.onDropCompleted(UninstallDropTarget.this, mDragObject, false, false);
}
- return canUninstall;
- }
-
- /**
- * Notifies the {@param callback} whether the uninstall was successful or not.
- *
- * Since there is no direct callback for an uninstall request, we check the package existence
- * when the launch resumes next time. This assumes that the uninstall activity will finish only
- * after the task is completed
- */
- protected static void sendUninstallResult(
- final Launcher launcher, boolean activityStarted,
- final ComponentName cn, final UserHandle user,
- final DropTargetResultCallback callback) {
- if (activityStarted) {
- final Runnable checkIfUninstallWasSuccess = new Runnable() {
- @Override
- public void run() {
- // We use MATCH_UNINSTALLED_PACKAGES as the app can be on SD card as well.
- boolean uninstallSuccessful = LauncherAppsCompat.getInstance(launcher)
- .getApplicationInfo(cn.getPackageName(),
- PackageManager.MATCH_UNINSTALLED_PACKAGES, user) == null;
- callback.onDragObjectRemoved(uninstallSuccessful);
- }
- };
- launcher.addOnResumeCallback(checkIfUninstallWasSuccess);
- } else {
- callback.onDragObjectRemoved(false);
- }
- }
-
- public interface DropTargetResultCallback {
- /**
- * A drag operation was complete.
- * @param isRemoved true if the drag object should be removed, false otherwise.
- */
- void onDragObjectRemoved(boolean isRemoved);
- }
-
- /**
- * Interface defining an object that can provide uninstallable drag objects.
- */
- public interface DropTargetSource extends DropTargetResultCallback {
-
- /**
- * Indicates that an uninstall request are made and the actual result may come
- * after some time.
- */
- void deferCompleteDropAfterUninstallActivity();
}
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fff075e..1f26965 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -55,7 +55,6 @@
import com.android.launcher3.Launcher.LauncherOverlay;
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
-import com.android.launcher3.UninstallDropTarget.DropTargetSource;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.OverviewAccessibilityDelegate;
import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
@@ -99,7 +98,7 @@
public class Workspace extends PagedView
implements DropTarget, DragSource, View.OnTouchListener,
DragController.DragListener, ViewGroup.OnHierarchyChangeListener,
- Insettable, DropTargetSource {
+ Insettable {
private static final String TAG = "Launcher.Workspace";
/** The value that {@link #mTransitionProgress} must be greater than for
@@ -280,10 +279,6 @@
private float mCurrentScale;
private float mTransitionProgress;
- @Thunk Runnable mDeferredAction;
- private boolean mDeferDropAfterUninstall;
- private boolean mUninstallSuccessful;
-
// State related to Launcher Overlay
LauncherOverlay mLauncherOverlay;
boolean mScrollInteractionBegan;
@@ -407,7 +402,6 @@
updateChildrenLayersEnabled();
mLauncher.lockScreenOrientation();
- mLauncher.onInteractionBegin();
// Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_DRAG_AND_DROP);
@@ -466,9 +460,7 @@
InstallShortcutReceiver.FLAG_DRAG_AND_DROP, getContext());
mOutlineProvider = null;
- mDragInfo = null;
mDragSourceInternal = null;
- mLauncher.onInteractionEnd();
}
/**
@@ -1752,6 +1744,7 @@
}
});
}
+ options.deferCompleteForUninstall = true;
beginDragShared(child, this, options);
}
@@ -2035,7 +2028,7 @@
if (dropOverView instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) dropOverView;
if (fi.acceptDrop(d.dragInfo)) {
- fi.onDrop(d);
+ fi.onDrop(d, false /* itemReturnedOnFailedDrop */);
// if the drag started here, we need to remove it from the workspace
if (!external) {
@@ -2050,7 +2043,7 @@
@Override
public void prepareAccessibilityDrop() { }
- public void onDrop(final DragObject d) {
+ public void onDrop(final DragObject d, DragOptions options) {
mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
CellLayout dropTargetLayout = mDropToLayout;
@@ -3093,21 +3086,8 @@
*/
public void onDropCompleted(final View target, final DragObject d,
final boolean isFlingToDelete, final boolean success) {
- if (mDeferDropAfterUninstall) {
- final CellLayout.CellInfo dragInfo = mDragInfo;
- mDeferredAction = new Runnable() {
- public void run() {
- mDragInfo = dragInfo; // Restore the drag info that was cleared in onDragEnd()
- onDropCompleted(target, d, isFlingToDelete, success);
- mDeferredAction = null;
- }
- };
- return;
- }
- boolean beingCalledAfterUninstall = mDeferredAction != null;
-
- if (success && !(beingCalledAfterUninstall && !mUninstallSuccessful)) {
+ if (success) {
if (target != this && mDragInfo != null) {
removeWorkspaceItem(mDragInfo.cell);
}
@@ -3121,8 +3101,7 @@
+ "Workspace#onDropCompleted. Please file a bug. ");
}
}
- if ((d.cancelled || (beingCalledAfterUninstall && !mUninstallSuccessful))
- && mDragInfo != null && mDragInfo.cell != null) {
+ if (d.cancelled && mDragInfo != null && mDragInfo.cell != null) {
mDragInfo.cell.setVisibility(VISIBLE);
}
mDragInfo = null;
@@ -3169,21 +3148,6 @@
});
}
- @Override
- public void deferCompleteDropAfterUninstallActivity() {
- mDeferDropAfterUninstall = true;
- }
-
- /// maybe move this into a smaller part
- @Override
- public void onDragObjectRemoved(boolean success) {
- mDeferDropAfterUninstall = false;
- mUninstallSuccessful = success;
- if (mDeferredAction != null) {
- mDeferredAction.run();
- }
- }
-
public boolean isDropEnabled() {
return true;
}
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index c695758..583492e 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -152,7 +152,7 @@
DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host);
return true;
} else if (action == INFO) {
- InfoDropTarget.startDetailsActivityForInfo(item, mLauncher, null);
+ InfoDropTarget.startDetailsActivityForInfo(item, mLauncher, null, null);
return true;
} else if (action == UNINSTALL) {
return UninstallDropTarget.startUninstallActivity(mLauncher, item);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 2cc0781..b844ba3 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -275,8 +275,7 @@
private void updateAllAppsBg(float progress) {
// gradient
if (mGradientView == null) {
- mGradientView = (GradientView) mLauncher.findViewById(R.id.gradient_bg);
- mGradientView.setVisibility(View.VISIBLE);
+ mGradientView = mLauncher.findViewById(R.id.gradient_bg);
}
mGradientView.setProgress(progress);
}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index a7ed87f..db8f903 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -575,7 +575,7 @@
if (flingAnimation != null) {
flingAnimation.run();
} else if (!mIsInPreDrag) {
- dropTarget.onDrop(mDragObject);
+ dropTarget.onDrop(mDragObject, mOptions);
}
accepted = true;
}
diff --git a/src/com/android/launcher3/dragndrop/DragOptions.java b/src/com/android/launcher3/dragndrop/DragOptions.java
index f108f8b..550f948 100644
--- a/src/com/android/launcher3/dragndrop/DragOptions.java
+++ b/src/com/android/launcher3/dragndrop/DragOptions.java
@@ -38,6 +38,12 @@
public float intrinsicIconScaleFactor = 1f;
/**
+ * Whether or not to defer {@link com.android.launcher3.DragSource#onDropCompleted} until
+ * uninstall result is available when dropped on uninstall drop target.
+ */
+ public boolean deferCompleteForUninstall = false;
+
+ /**
* Specifies a condition that must be met before DragListener#onDragStart() is called.
* By default, there is no condition and onDragStart() is called immediately following
* DragController#startDrag().
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index e182da1..b930ad3 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -58,7 +58,6 @@
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
-import com.android.launcher3.UninstallDropTarget.DropTargetSource;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
@@ -84,8 +83,7 @@
*/
public class Folder extends AbstractFloatingView implements DragSource, View.OnClickListener,
View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
- View.OnFocusChangeListener, DragListener, DropTargetSource,
- ExtendedEditText.OnBackKeyListener {
+ View.OnFocusChangeListener, DragListener, ExtendedEditText.OnBackKeyListener {
private static final String TAG = "Launcher.Folder";
/**
@@ -172,10 +170,6 @@
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mDestroyed;
- @Thunk Runnable mDeferredAction;
- private boolean mDeferDropAfterUninstall;
- private boolean mUninstallSuccessful;
-
// Folder scrolling
private int mScrollAreaOffset;
@@ -289,6 +283,7 @@
}
});
}
+ options.deferCompleteForUninstall = true;
mLauncher.getWorkspace().beginDragShared(v, this, options);
}
@@ -856,22 +851,8 @@
public void onDropCompleted(final View target, final DragObject d,
final boolean isFlingToDelete, final boolean success) {
- if (mDeferDropAfterUninstall) {
- Log.d(TAG, "Deferred handling drop because waiting for uninstall.");
- mDeferredAction = new Runnable() {
- public void run() {
- onDropCompleted(target, d, isFlingToDelete, success);
- mDeferredAction = null;
- }
- };
- return;
- }
- boolean beingCalledAfterUninstall = mDeferredAction != null;
- boolean successfulDrop =
- success && (!beingCalledAfterUninstall || mUninstallSuccessful);
-
- if (successfulDrop) {
+ if (success) {
if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon && target != this) {
replaceFolderWithFinalItem();
}
@@ -886,14 +867,14 @@
mItemsInvalidated = true;
try (SuppressInfoChanges s = new SuppressInfoChanges()) {
- mFolderIcon.onDrop(d);
+ mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */);
}
}
if (target != this) {
if (mOnExitAlarm.alarmPending()) {
mOnExitAlarm.cancelAlarm();
- if (!successfulDrop) {
+ if (!success) {
mSuppressFolderDeletion = true;
}
mScrollPauseAlarm.cancelAlarm();
@@ -920,25 +901,11 @@
if (!isFlingToDelete) {
// Fling to delete already exits spring loaded mode after the animation finishes.
- mLauncher.exitSpringLoadedDragModeDelayed(successfulDrop,
+ mLauncher.exitSpringLoadedDragModeDelayed(success,
Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
}
}
- @Override
- public void deferCompleteDropAfterUninstallActivity() {
- mDeferDropAfterUninstall = true;
- }
-
- @Override
- public void onDragObjectRemoved(boolean success) {
- mDeferDropAfterUninstall = false;
- mUninstallSuccessful = success;
- if (mDeferredAction != null) {
- mDeferredAction.run();
- }
- }
-
private void updateItemLocationsInDatabaseBatch() {
ArrayList<View> list = getItemsInReadingOrder();
ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
@@ -1190,7 +1157,7 @@
}
}
- public void onDrop(DragObject d) {
+ public void onDrop(DragObject d, DragOptions options) {
Runnable cleanUpRunnable = null;
// If we are coming from All Apps space, we defer removing the extra empty screen
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index bb0a726..3998888 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -100,6 +100,7 @@
ClippedFolderIconLayoutRule mPreviewLayoutRule;
private PreviewItemManager mPreviewItemManager;
private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
+ private List<BubbleTextView> mCurrentPreviewItems = new ArrayList<>();
boolean mAnimating = false;
private Rect mTempBounds = new Rect();
@@ -198,7 +199,7 @@
private void setFolder(Folder folder) {
mFolder = folder;
mPreviewVerifier = new FolderIconPreviewVerifier(mLauncher.getDeviceProfile().inv);
- mPreviewItemManager.updateItemDrawingParams(false);
+ updatePreviewItems(false);
}
private boolean willAcceptItem(ItemInfo item) {
@@ -262,7 +263,8 @@
.start();
// This will animate the dragView (srcView) into the new folder
- onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable);
+ onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable,
+ false /* itemReturnedOnFailedDrop */);
}
public void performDestroyAnimation(Runnable onCompleteRunnable) {
@@ -277,7 +279,8 @@
}
private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
- float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable) {
+ float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable,
+ boolean itemReturnedOnFailedDrop) {
item.cellX = -1;
item.cellY = -1;
@@ -305,21 +308,25 @@
workspace.resetTransitionTransform((CellLayout) getParent().getParent());
}
+ int numItemsInPreview = Math.min(MAX_NUM_ITEMS_IN_PREVIEW, index + 1);
boolean itemAdded = false;
- if (index >= MAX_NUM_ITEMS_IN_PREVIEW) {
- List<BubbleTextView> oldPreviewItems = getPreviewItemsOnPage(0);
+ if (itemReturnedOnFailedDrop || index >= MAX_NUM_ITEMS_IN_PREVIEW) {
+ List<BubbleTextView> oldPreviewItems = new ArrayList<>(mCurrentPreviewItems);
addItem(item, false);
- List<BubbleTextView> newPreviewItems = getPreviewItemsOnPage(0);
+ mCurrentPreviewItems.clear();
+ mCurrentPreviewItems.addAll(getPreviewItems());
- if (!oldPreviewItems.containsAll(newPreviewItems)) {
- for (int i = 0; i < newPreviewItems.size(); ++i) {
- if (newPreviewItems.get(i).getTag().equals(item)) {
+ if (!oldPreviewItems.equals(mCurrentPreviewItems)) {
+ for (int i = 0; i < mCurrentPreviewItems.size(); ++i) {
+ if (mCurrentPreviewItems.get(i).getTag().equals(item)) {
// If the item dropped is going to be in the preview, we update the
// index here to reflect its position in the preview.
index = i;
}
}
- mPreviewItemManager.onDrop(oldPreviewItems, newPreviewItems, item);
+
+ mPreviewItemManager.hidePreviewItem(index, true);
+ mPreviewItemManager.onDrop(oldPreviewItems, mCurrentPreviewItems, item);
itemAdded = true;
} else {
removeItem(item, false);
@@ -331,7 +338,7 @@
}
int[] center = new int[2];
- float scale = getLocalCenterForIndex(index, index + 1, center);
+ float scale = getLocalCenterForIndex(index, numItemsInPreview, center);
center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]);
center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]);
@@ -362,7 +369,7 @@
}
}
- public void onDrop(DragObject d) {
+ public void onDrop(DragObject d, boolean itemReturnedOnFailedDrop) {
ShortcutInfo item;
if (d.dragInfo instanceof AppInfo) {
// Came from all apps -- make a copy
@@ -374,7 +381,8 @@
item = (ShortcutInfo) d.dragInfo;
}
mFolder.notifyDrop();
- onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable);
+ onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable,
+ itemReturnedOnFailedDrop);
}
public void setBadgeInfo(FolderBadgeInfo badgeInfo) {
@@ -545,11 +553,17 @@
@Override
public void onItemsChanged(boolean animate) {
- mPreviewItemManager.updateItemDrawingParams(animate);
+ updatePreviewItems(animate);
invalidate();
requestLayout();
}
+ private void updatePreviewItems(boolean animate) {
+ mPreviewItemManager.updatePreviewItems(animate);
+ mCurrentPreviewItems.clear();
+ mCurrentPreviewItems.addAll(getPreviewItems());
+ }
+
@Override
public void prepareAutoUpdate() {
}
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 5d40010..06d3eb1 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -110,7 +110,7 @@
mIcon.mPreviewLayoutRule.init(mIcon.mBackground.previewSize, mIntrinsicIconSize,
Utilities.isRtl(mIcon.getResources()));
- updateItemDrawingParams(false);
+ updatePreviewItems(false);
}
}
@@ -185,6 +185,11 @@
}
public void hidePreviewItem(int index, boolean hidden) {
+ // If there are more params than visible in the preview, they are used for enter/exit
+ // animation purposes and they were added to the front of the list.
+ // To index the params properly, we need to skip these params.
+ index = index + Math.max(mFirstPageParams.size() - MAX_NUM_ITEMS_IN_PREVIEW, 0);
+
PreviewItemDrawingParams params = index < mFirstPageParams.size() ?
mFirstPageParams.get(index) : null;
if (params != null) {
@@ -266,7 +271,7 @@
}
}
- void updateItemDrawingParams(boolean animate) {
+ void updatePreviewItems(boolean animate) {
buildParamsForPage(0, mFirstPageParams, animate);
}
@@ -310,8 +315,8 @@
int prevIndex = newParams.indexOf(moveIn.get(i));
PreviewItemDrawingParams p = params.get(prevIndex);
computePreviewItemDrawingParams(prevIndex, numItems, p);
- updateTransitionParam(p, moveIn.get(i), ENTER_INDEX,
- newParams.indexOf(moveIn.get(i)));
+ updateTransitionParam(p, moveIn.get(i), ENTER_INDEX, newParams.indexOf(moveIn.get(i)),
+ numItems);
}
// Items that are moving into new positions within the preview.
@@ -319,7 +324,7 @@
int oldIndex = oldParams.indexOf(newParams.get(newIndex));
if (oldIndex >= 0 && newIndex != oldIndex) {
PreviewItemDrawingParams p = params.get(newIndex);
- updateTransitionParam(p, newParams.get(newIndex), oldIndex, newIndex);
+ updateTransitionParam(p, newParams.get(newIndex), oldIndex, newIndex, numItems);
}
}
@@ -330,7 +335,7 @@
BubbleTextView item = moveOut.get(i);
int oldIndex = oldParams.indexOf(item);
PreviewItemDrawingParams p = computePreviewItemDrawingParams(oldIndex, numItems, null);
- updateTransitionParam(p, item, oldIndex, EXIT_INDEX);
+ updateTransitionParam(p, item, oldIndex, EXIT_INDEX, numItems);
params.add(0, p); // We want these items first so that they are on drawn last.
}
@@ -342,7 +347,7 @@
}
private void updateTransitionParam(final PreviewItemDrawingParams p, BubbleTextView btv,
- int prevIndex, int newIndex) {
+ int prevIndex, int newIndex, int numItems) {
p.drawable = btv.getCompoundDrawables()[1];
if (!mIcon.mFolder.isOpen()) {
// Set the callback to FolderIcon as it is responsible to drawing the icon. The
@@ -350,9 +355,8 @@
p.drawable.setCallback(mIcon);
}
- FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, prevIndex,
- MAX_NUM_ITEMS_IN_PREVIEW, newIndex, MAX_NUM_ITEMS_IN_PREVIEW,
- DROP_IN_ANIMATION_DURATION, null);
+ FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, prevIndex, numItems,
+ newIndex, numItems, DROP_IN_ANIMATION_DURATION, null);
if (p.anim != null && !p.anim.hasEqualFinalState(anim)) {
p.anim.cancel();
}
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 42926fa..a33a039 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -38,7 +38,6 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.ManagedProfileHeuristic.UserFolderInfo;
-import com.android.launcher3.util.Provider;
import java.util.ArrayList;
import java.util.List;
@@ -47,19 +46,18 @@
*/
public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
- private final Provider<List<Pair<ItemInfo, Object>>> mAppsProvider;
+ private final List<Pair<ItemInfo, Object>> mItemList;
/**
- * @param appsProvider items to add on the workspace
+ * @param itemList items to add on the workspace
*/
- public AddWorkspaceItemsTask(Provider<List<Pair<ItemInfo, Object>>> appsProvider) {
- mAppsProvider = appsProvider;
+ public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList) {
+ mItemList = itemList;
}
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
- List<Pair<ItemInfo, Object>> workspaceApps = mAppsProvider.get();
- if (workspaceApps.isEmpty()) {
+ if (mItemList.isEmpty()) {
return;
}
Context context = app.getContext();
@@ -75,7 +73,7 @@
synchronized(dataModel) {
List<ItemInfo> filteredItems = new ArrayList<>();
- for (Pair<ItemInfo, Object> entry : workspaceApps) {
+ for (Pair<ItemInfo, Object> entry : mItemList) {
ItemInfo item = entry.first;
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
diff --git a/src/com/android/launcher3/notification/NotificationGroup.java b/src/com/android/launcher3/notification/NotificationGroup.java
new file mode 100644
index 0000000..bce2117
--- /dev/null
+++ b/src/com/android/launcher3/notification/NotificationGroup.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 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.notification;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Contains data related to a group of notifications, like the group summary key and the child keys.
+ */
+public class NotificationGroup {
+ private String mGroupSummaryKey;
+ private Set<String> mChildKeys;
+
+ public NotificationGroup() {
+ mChildKeys = new HashSet<>();
+ }
+
+ public void setGroupSummaryKey(String groupSummaryKey) {
+ mGroupSummaryKey = groupSummaryKey;
+ }
+
+ public String getGroupSummaryKey() {
+ return mGroupSummaryKey;
+ }
+
+ public void addChildKey(String childKey) {
+ mChildKeys.add(childKey);
+ }
+
+ public void removeChildKey(String childKey) {
+ mChildKeys.remove(childKey);
+ }
+
+ public boolean isEmpty() {
+ return mChildKeys.isEmpty();
+ }
+}
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 9126626..7b70df7 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -38,7 +38,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING;
@@ -66,6 +68,8 @@
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<>();
private SettingsObserver mNotificationBadgingObserver;
@@ -227,6 +231,15 @@
NotificationKeyData.fromNotification(sbn));
mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, packageUserKeyAndNotificationKey)
.sendToTarget();
+
+ NotificationGroup notificationGroup = mNotificationGroupMap.get(sbn.getGroupKey());
+ if (notificationGroup != null) {
+ notificationGroup.removeChildKey(sbn.getKey());
+ if (notificationGroup.isEmpty()) {
+ cancelNotification(notificationGroup.getGroupSummaryKey());
+ mNotificationGroupMap.remove(sbn.getGroupKey());
+ }
+ }
}
/** This makes a potentially expensive binder call and should be run on a background thread. */
@@ -264,18 +277,34 @@
}
private boolean shouldBeFilteredOut(StatusBarNotification sbn) {
+ Notification notification = sbn.getNotification();
+
+ boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
+ if (sbn.isGroup()) {
+ // Maintain group info so we can cancel the summary when the last child is canceled.
+ NotificationGroup notificationGroup = mNotificationGroupMap.get(sbn.getGroupKey());
+ if (notificationGroup == null) {
+ notificationGroup = new NotificationGroup();
+ mNotificationGroupMap.put(sbn.getGroupKey(), notificationGroup);
+ }
+ if (isGroupHeader) {
+ notificationGroup.setGroupSummaryKey(sbn.getKey());
+ } else {
+ notificationGroup.addChildKey(sbn.getKey());
+ }
+ }
+
getCurrentRanking().getRanking(sbn.getKey(), mTempRanking);
if (!mTempRanking.canShowBadge()) {
return true;
}
- Notification notification = sbn.getNotification();
if (mTempRanking.getChannel().getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
// Special filtering for the default, legacy "Miscellaneous" channel.
if ((notification.flags & Notification.FLAG_ONGOING_EVENT) != 0) {
return true;
}
}
- boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
+
CharSequence title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
CharSequence text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
boolean missingTitleAndText = TextUtils.isEmpty(title) && TextUtils.isEmpty(text);
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index a342500..3f7bf42 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -92,7 +92,7 @@
public void onClick(View view) {
Rect sourceBounds = launcher.getViewBounds(view);
Bundle opts = launcher.getActivityLaunchOptions(view);
- InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, null, sourceBounds, opts);
+ InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, sourceBounds, opts);
launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
ControlType.APPINFO_TARGET, view);
}
diff --git a/src/com/android/launcher3/testing/LauncherExtension.java b/src/com/android/launcher3/testing/LauncherExtension.java
index a1a4d75..c40e1fb 100644
--- a/src/com/android/launcher3/testing/LauncherExtension.java
+++ b/src/com/android/launcher3/testing/LauncherExtension.java
@@ -36,10 +36,6 @@
}
@Override
- public void preOnResume() {
- }
-
- @Override
public void onResume() {
}
@@ -64,10 +60,6 @@
}
@Override
- public void onPostCreate(Bundle savedInstanceState) {
- }
-
- @Override
public void onNewIntent(Intent intent) {
}
@@ -111,37 +103,16 @@
}
@Override
- public void finishBindingItems(boolean upgradePath) {
- }
-
- @Override
public void bindAllApplications(ArrayList<AppInfo> apps) {
}
@Override
- public void onWorkspaceLockedChanged() {
- }
-
- @Override
- public void onInteractionBegin() {
- }
-
- @Override
- public void onInteractionEnd() {
- }
-
- @Override
public boolean startSearch(String initialQuery, boolean selectInitialQuery,
Bundle appSearchData) {
return false;
}
@Override
- public boolean shouldMoveToDefaultScreenOnHomeIntent() {
- return true;
- }
-
- @Override
public boolean hasSettings() {
return false;
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 432efa7..7aa50a4 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -107,7 +107,6 @@
onWidgetsBound();
mLauncher.getDragLayer().addView(mGradientBackground);
- mGradientBackground.setVisibility(VISIBLE);
mLauncher.getDragLayer().addView(this);
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
setTranslationY(mTranslationYClosed);
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
index 82f34e4..a486ceb 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
@@ -55,7 +55,7 @@
for (ItemInfo item : items) {
list.add(Pair.create(item, null));
}
- return new AddWorkspaceItemsTask(Provider.of(list)) {
+ return new AddWorkspaceItemsTask(list) {
@Override
protected void updateScreens(Context context, ArrayList<Long> workspaceScreens) { }