diff options
Diffstat (limited to 'src/com/android/launcher3/BaseDraggingActivity.java')
-rw-r--r-- | src/com/android/launcher3/BaseDraggingActivity.java | 148 |
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); } } |