Adding support for listening to end callbacks when launching an intent from Launcher
Also moving various state handling to these end callbacks enstead of relying on resume
Bug: 265134143
Test: Verified that the end callback is received
Change-Id: I326a99c80154d244c0e49f678717c476602b6240
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 45b03c2..8876a1b 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -156,6 +156,13 @@
}
@Override
+ public ActivityOptionsWrapper makeDefaultActivityOptions(int splashScreenStyle) {
+ ActivityOptionsWrapper wrapper = super.makeDefaultActivityOptions(splashScreenStyle);
+ addOnResumeCallback(wrapper.onEndCallback::executeAllAndDestroy);
+ return wrapper;
+ }
+
+ @Override
protected void onStart() {
super.onStart();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ffd56cc..faf5c6a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2154,30 +2154,38 @@
}
@Override
- public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
+ public RunnableList startActivitySafely(View v, Intent intent, ItemInfo item) {
if (!hasBeenResumed()) {
+ RunnableList result = new RunnableList();
// Workaround an issue where the WM launch animation is clobbered when finishing the
// recents animation into launcher. Defer launching the activity until Launcher is
// next resumed.
- addOnResumeCallback(() -> startActivitySafely(v, intent, item));
+ addOnResumeCallback(() -> {
+ RunnableList actualResult = startActivitySafely(v, intent, item);
+ if (actualResult != null) {
+ actualResult.add(result::executeAllAndDestroy);
+ } else {
+ result.executeAllAndDestroy();
+ }
+ });
if (mOnDeferredActivityLaunchCallback != null) {
mOnDeferredActivityLaunchCallback.run();
mOnDeferredActivityLaunchCallback = null;
}
- return true;
+ return result;
}
- boolean success = super.startActivitySafely(v, intent, item);
- if (success && v instanceof BubbleTextView) {
+ RunnableList result = super.startActivitySafely(v, intent, item);
+ if (result != null && 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);
- addOnResumeCallback(() -> btv.setStayPressed(false));
+ result.add(() -> btv.setStayPressed(false));
}
- return success;
+ return result;
}
boolean isHotseatLayout(View layout) {
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index 714304b..64fd237 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -62,7 +62,8 @@
if (mHighlightedView instanceof BubbleTextView
&& mHighlightedView.getTag() instanceof ItemInfo) {
ItemInfo itemInfo = (ItemInfo) mHighlightedView.getTag();
- return mLauncher.startActivitySafely(mHighlightedView, itemInfo.getIntent(), itemInfo);
+ return mLauncher.startActivitySafely(
+ mHighlightedView, itemInfo.getIntent(), itemInfo) != null;
}
return false;
}
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index 31b1934..515a2d8 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -15,6 +15,9 @@
*/
package com.android.launcher3.views;
+import static android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR;
+
+import static com.android.launcher3.LauncherSettings.Animation.DEFAULT_NO_ICON;
import static com.android.launcher3.logging.KeyboardStateManager.KeyboardState.HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_KEYBOARD_CLOSED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
@@ -45,7 +48,6 @@
import android.view.WindowInsetsController;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
-import android.window.SplashScreen;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -289,27 +291,27 @@
}
}
-
/**
* Sends a pending intent animating from a view.
*
* @param v View to animate.
* @param intent The pending intent being launched.
* @param item Item associated with the view.
- * @return {@code true} if the intent is sent successfully.
+ * @return RunnableList for listening for animation finish if the activity was properly
+ * or started, {@code null} if the launch finished
*/
- default boolean sendPendingIntentWithAnimation(
+ default RunnableList sendPendingIntentWithAnimation(
@NonNull View v, PendingIntent intent, @Nullable ItemInfo item) {
- Bundle optsBundle = getActivityLaunchOptions(v, item).toBundle();
+ ActivityOptionsWrapper options = getActivityLaunchOptions(v, item);
try {
- intent.send(null, 0, null, null, null, null, optsBundle);
- return true;
+ intent.send(null, 0, null, null, null, null, options.toBundle());
+ return options.onEndCallback;
} catch (PendingIntent.CanceledException e) {
Toast.makeText(v.getContext(),
v.getContext().getResources().getText(R.string.shortcut_not_available),
Toast.LENGTH_SHORT).show();
}
- return false;
+ return null;
}
/**
@@ -318,28 +320,23 @@
* @param v View starting the activity.
* @param intent Base intent being launched.
* @param item Item associated with the view.
- * @return {@code true} if the activity starts successfully.
+ * @return RunnableList for listening for animation finish if the activity was properly
+ * or started, {@code null} if the launch finished
*/
- default boolean startActivitySafely(
+ default RunnableList startActivitySafely(
View v, Intent intent, @Nullable ItemInfo item) {
Preconditions.assertUIThread();
Context context = (Context) this;
if (isAppBlockedForSafeMode() && !PackageManagerHelper.isSystemApp(context, intent)) {
Toast.makeText(context, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
- return false;
+ return null;
}
- Bundle optsBundle = null;
- if (v != null) {
- optsBundle = getActivityLaunchOptions(v, item).toBundle();
- } else if (android.os.Build.VERSION.SDK_INT >= 33
- && item != null
- && item.animationType == LauncherSettings.Animation.DEFAULT_NO_ICON) {
- optsBundle = ActivityOptions.makeBasic()
- .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR).toBundle();
- }
+ ActivityOptionsWrapper options = v != null ? getActivityLaunchOptions(v, item)
+ : makeDefaultActivityOptions(item != null && item.animationType == DEFAULT_NO_ICON
+ ? SPLASH_SCREEN_STYLE_SOLID_COLOR : -1 /* SPLASH_SCREEN_STYLE_UNDEFINED */);
UserHandle user = item == null ? null : item.user;
-
+ Bundle optsBundle = options.toBundle();
// Prepare intent
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (v != null) {
@@ -364,12 +361,12 @@
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
logAppLaunch(getStatsLogManager(), item, instanceId);
}
- return true;
+ return options.onEndCallback;
} catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
Toast.makeText(context, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
}
- return false;
+ return null;
}
/** Returns {@code true} if an app launch is blocked due to safe mode. */
@@ -417,6 +414,17 @@
}
/**
+ * Creates a default activity option and we do not want association with any launcher element.
+ */
+ default ActivityOptionsWrapper makeDefaultActivityOptions(int splashScreenStyle) {
+ ActivityOptions options = ActivityOptions.makeBasic();
+ if (Utilities.ATLEAST_T) {
+ options.setSplashScreenStyle(splashScreenStyle);
+ }
+ return new ActivityOptionsWrapper(options, new RunnableList());
+ }
+
+ /**
* Safely launches an intent for a shortcut.
*
* @param intent Intent to start.
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 64ad390..ba6165f 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -281,7 +281,7 @@
if (!TextUtils.isEmpty(pickerPackage)) {
intent.setPackage(pickerPackage);
}
- return launcher.startActivitySafely(v, intent, placeholderInfo(intent));
+ return launcher.startActivitySafely(v, intent, placeholderInfo(intent)) != null;
}
static WorkspaceItemInfo placeholderInfo(Intent intent) {