Fixing taskMenu and taskView clicks in fallback activity
> Extracting common methods from Launcher & DragLauncher to base classes
> Remoting some dependencies on Launcher and using the base class instead
Change-Id: I121cacf8a14190b4703cda60bdeb4f79eee69ded
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
new file mode 100644
index 0000000..35edaf4
--- /dev/null
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -0,0 +1,191 @@
+/*
+ * 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.launcher3;
+
+import android.app.ActivityOptions;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.graphics.Rect;
+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.View;
+import android.widget.Toast;
+
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.badge.BadgeInfo;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.views.BaseDragLayer;
+
+/**
+ * Extension of BaseActivity allowing support for drag-n-drop
+ */
+public abstract class BaseDraggingActivity extends BaseActivity {
+
+ private static final String TAG = "BaseDraggingActivity";
+
+ // The Intent extra that defines whether to ignore the launch animation
+ private static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION =
+ "com.android.launcher3.intent.extra.shortcut.INGORE_LAUNCH_ANIMATION";
+
+ // When starting an action mode, setting this tag will cause the action mode to be cancelled
+ // automatically when user interacts with the launcher.
+ public static final Object AUTO_CANCEL_ACTION_MODE = new Object();
+
+ private ActionMode mCurrentActionMode;
+ protected boolean mIsSafeModeEnabled;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mIsSafeModeEnabled = getPackageManager().isSafeMode();
+ }
+
+ @Override
+ public void onActionModeStarted(ActionMode mode) {
+ super.onActionModeStarted(mode);
+ mCurrentActionMode = mode;
+ }
+
+ @Override
+ public void onActionModeFinished(ActionMode mode) {
+ super.onActionModeFinished(mode);
+ mCurrentActionMode = null;
+ }
+
+ public boolean finishAutoCancelActionMode() {
+ if (mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag()) {
+ mCurrentActionMode.finish();
+ return true;
+ }
+ return false;
+ }
+
+ public abstract BaseDragLayer getDragLayer();
+
+ public abstract <T extends View> T getOverviewPanel();
+
+ public abstract BadgeInfo getBadgeInfoForItem(ItemInfo info);
+
+ public abstract void invalidateParent(ItemInfo info);
+
+ public static BaseDraggingActivity fromContext(Context context) {
+ if (context instanceof BaseDraggingActivity) {
+ return (BaseDraggingActivity) context;
+ }
+ return ((BaseDraggingActivity) ((ContextWrapper) context).getBaseContext());
+ }
+
+ 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());
+ }
+
+ public final Bundle getActivityLaunchOptionsAsBundle(View v, boolean useDefaultLaunchOptions) {
+ ActivityOptions activityOptions = getActivityLaunchOptions(v, useDefaultLaunchOptions);
+ return activityOptions == null ? null : activityOptions.toBundle();
+ }
+
+ public abstract ActivityOptions getActivityLaunchOptions(
+ View v, boolean useDefaultLaunchOptions);
+
+ public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
+ if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
+ Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
+ return false;
+ }
+
+ // Only launch using the new animation if the shortcut has not opted out (this is a
+ // private contract between launcher and may be ignored in the future).
+ boolean useLaunchAnimation = (v != null) &&
+ !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
+ Bundle optsBundle = useLaunchAnimation
+ ? getActivityLaunchOptionsAsBundle(v, isInMultiWindowModeCompat())
+ : 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 = Utilities.ATLEAST_MARSHMALLOW
+ && (item instanceof ShortcutInfo)
+ && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
+ || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
+ && !((ShortcutInfo) 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 {
+ LauncherAppsCompat.getInstance(this).startActivityForProfile(
+ intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
+ }
+ getUserEventDispatcher().logAppLaunch(v, intent);
+ return true;
+ } catch (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;
+ }
+
+ 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 = ((ShortcutInfo) info).getDeepShortcutId();
+ String packageName = intent.getPackage();
+ DeepShortcutManager.getInstance(this).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;
+ }
+}