summaryrefslogtreecommitdiff
path: root/src/com/android/launcher3/BaseDraggingActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/BaseDraggingActivity.java')
-rw-r--r--src/com/android/launcher3/BaseDraggingActivity.java148
1 files changed, 131 insertions, 17 deletions
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 6de3884b93..2c76e52c61 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -16,33 +16,53 @@
package com.android.launcher3;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import android.app.ActivityOptions;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.app.WallpaperManager.OnColorsChangedListener;
+import android.content.ActivityNotFoundException;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
import android.content.res.Configuration;
+import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Process;
+import android.os.StrictMode;
+import android.os.UserHandle;
+import android.util.Log;
import android.view.ActionMode;
import android.view.Display;
import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.WindowInsets.Type;
+import android.view.WindowMetrics;
+import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
+import com.android.launcher3.logging.InstanceId;
+import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
+import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TraceHelper;
@@ -145,12 +165,110 @@ public abstract class BaseDraggingActivity extends BaseActivity
// no-op
}
- @Override
+ public Rect getViewBounds(View v) {
+ int[] pos = new int[2];
+ v.getLocationOnScreen(pos);
+ return new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight());
+ }
+
@NonNull
public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
- ActivityOptionsWrapper wrapper = super.getActivityLaunchOptions(v, item);
- addOnResumeCallback(wrapper.onEndCallback::executeAllAndDestroy);
- return wrapper;
+ int left = 0, top = 0;
+ int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
+ if (v instanceof BubbleTextView) {
+ // Launch from center of icon, not entire view
+ Drawable icon = ((BubbleTextView) v).getIcon();
+ if (icon != null) {
+ Rect bounds = icon.getBounds();
+ left = (width - bounds.width()) / 2;
+ top = v.getPaddingTop();
+ width = bounds.width();
+ height = bounds.height();
+ }
+ }
+ ActivityOptions options =
+ ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
+ RunnableList callback = new RunnableList();
+ addOnResumeCallback(callback::executeAllAndDestroy);
+ return new ActivityOptionsWrapper(options, callback);
+ }
+
+ public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {
+ if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
+ Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+
+ Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;
+ UserHandle user = item == null ? null : item.user;
+
+ // Prepare intent
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ if (v != null) {
+ intent.setSourceBounds(getViewBounds(v));
+ }
+ try {
+ boolean isShortcut = (item instanceof WorkspaceItemInfo)
+ && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
+ || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
+ && !((WorkspaceItemInfo) item).isPromise();
+ if (isShortcut) {
+ // Shortcuts need some special checks due to legacy reasons.
+ startShortcutIntentSafely(intent, optsBundle, item);
+ } else if (user == null || user.equals(Process.myUserHandle())) {
+ // Could be launching some bookkeeping activity
+ startActivity(intent, optsBundle);
+ } else {
+ getSystemService(LauncherApps.class).startMainActivity(
+ intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
+ }
+ if (item != null) {
+ InstanceId instanceId = new InstanceIdSequence().newInstanceId();
+ logAppLaunch(item, instanceId);
+ }
+ return true;
+ } catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
+ Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+ Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
+ }
+ return false;
+ }
+
+ protected void logAppLaunch(ItemInfo info, InstanceId instanceId) {
+ getStatsLogManager().logger().withItemInfo(info).withInstanceId(instanceId)
+ .log(LAUNCHER_APP_LAUNCH_TAP);
+ }
+
+ private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
+ try {
+ StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
+ try {
+ // Temporarily disable deathPenalty on all default checks. For eg, shortcuts
+ // containing file Uri's would cause a crash as penaltyDeathOnFileUriExposure
+ // is enabled by default on NYC.
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
+ .penaltyLog().build());
+
+ if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ String id = ((WorkspaceItemInfo) info).getDeepShortcutId();
+ String packageName = intent.getPackage();
+ startShortcut(packageName, id, intent.getSourceBounds(), optsBundle, info.user);
+ } else {
+ // Could be launching some bookkeeping activity
+ startActivity(intent, optsBundle);
+ }
+ } finally {
+ StrictMode.setVmPolicy(oldPolicy);
+ }
+ } catch (SecurityException e) {
+ if (!onErrorStartingShortcut(intent, info)) {
+ throw e;
+ }
+ }
+ }
+
+ protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
+ return false;
}
@Override
@@ -193,8 +311,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
}
}
- @Override
- public View.OnClickListener getItemOnClickListener() {
+ public OnClickListener getItemOnClickListener() {
return ItemClickHandler.INSTANCE;
}
@@ -202,7 +319,11 @@ public abstract class BaseDraggingActivity extends BaseActivity
protected WindowBounds getMultiWindowDisplaySize() {
if (Utilities.ATLEAST_R) {
- return WindowBounds.fromWindowMetrics(getWindowManager().getCurrentWindowMetrics());
+ WindowMetrics wm = getWindowManager().getCurrentWindowMetrics();
+
+ Insets insets = wm.getWindowInsets().getInsets(Type.systemBars());
+ return new WindowBounds(wm.getBounds(),
+ new Rect(insets.left, insets.top, insets.right, insets.bottom));
}
// Note: Calls to getSize() can't rely on our cached DefaultDisplay since it can return
// the app window size
@@ -216,14 +337,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
* Creates and returns {@link SearchAdapterProvider} for build variant specific search result
* views
*/
- @Override
- public SearchAdapterProvider<?> createSearchAdapterProvider(
- ActivityAllAppsContainerView<?> allApps) {
- return new DefaultSearchAdapterProvider(this);
- }
-
- @Override
- public boolean isAppBlockedForSafeMode() {
- return mIsSafeModeEnabled;
+ public SearchAdapterProvider createSearchAdapterProvider(AllAppsContainerView allapps) {
+ return new DefaultSearchAdapterProvider(this, allapps);
}
}