Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 642da11e authored by Diogo Ferreira's avatar Diogo Ferreira Committed by Steve Kondik
Browse files

Recents: Port "Development shortcut" (2/3)

This patch includes the equivalent of our Development Shortcuts in
CM11 recents. Recents is very different now and this is mostly a rewrite.

The semantics changed a bit as well. The current code already has special
developer behavior when long-pressing the app icon and that is also where
the developer shortcuts are hooked. If the app icon is long-pressed and
developer shortcuts are active, a menu will be shown with the several available
options.

Fixes CML-61

Change-Id: Ifdeaf83cf8db0f41ea38a9e8e926109c569b091a
parent c372073c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -6600,6 +6600,7 @@ public final class Settings {
        public static final String CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED =
                "camera_double_tap_power_gesture_disabled";


        /**
         * This are the settings to be backed up.
         *
@@ -6657,7 +6658,7 @@ public final class Settings {
            SLEEP_TIMEOUT,
            DOUBLE_TAP_TO_WAKE,
            ADVANCED_REBOOT,
            CAMERA_GESTURE_DISABLED,
            CAMERA_GESTURE_DISABLED
        };

        /**
+26 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
/* apps/common/assets/default/default/skins/StatusBar.xml
**
** Copyright 2011, 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.
*/
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/recent_remove_item" android:title="@string/status_bar_recent_remove_item_title" />
    <item android:id="@+id/recent_inspect_item" android:title="@string/status_bar_recent_inspect_item_title" />
    <item android:id="@+id/recent_force_stop" android:title="@string/advanced_dev_option_force_stop" />
    <item android:id="@+id/recent_wipe_app" android:title="@string/advanced_dev_option_wipe_app" />
    <item android:id="@+id/recent_uninstall" android:title="@string/advanced_dev_option_uninstall" />
</menu>
+13 −0
Original line number Diff line number Diff line
@@ -53,4 +53,17 @@
    <string name="navbar_menu_big_button">Menu button</string>
    <string name="accessibility_dpad_left">Cursor left</string>
    <string name="accessibility_dpad_right">Cursor right</string>

    <!-- Development shortcuts -->
    <!-- Title shown in recents popup for removing an application from the list -->
    <string name="status_bar_recent_remove_item_title">Remove from list</string>
    <!-- Title shown in recents popup for inspecting an application's properties -->
    <string name="status_bar_recent_inspect_item_title">App info</string>
    <!-- Title shown in recents popup for wiping application's data -->
    <string name="advanced_dev_option_wipe_app">Wipe app data</string>
    <!-- Title shown in recents popup for force stopping the application -->
    <string name="advanced_dev_option_force_stop">Force stop</string>
    <!-- Title shown in recents popup for uninstalling the application -->
    <string name="advanced_dev_option_uninstall">Uninstall</string>

</resources>
+91 −0
Original line number Diff line number Diff line
@@ -17,18 +17,27 @@
package com.android.systemui.recents.views;

import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.PopupMenu;

import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
@@ -85,6 +94,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
    boolean mDismissAllButtonAnimating;
    int mFocusedTaskIndex = -1;
    int mPrevAccessibilityFocusedIndex = -1;

    private PopupMenu mPopup;

    // Optimizations
    int mStackViewsAnimationDuration;
    boolean mStackViewsDirty = true;
@@ -1371,6 +1383,85 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
        }
    }

    @Override
    public void onTaskViewLongClicked(final TaskView tv) {
        final PopupMenu popup = new PopupMenu(getContext(), tv.mHeaderView.mApplicationIcon);
        mPopup = popup;
        popup.getMenuInflater().inflate(R.menu.recent_popup_menu, popup.getMenu());

        final Task task = tv.getTask();
        final String packageName = task.key.baseIntent.getComponent().getPackageName();

        try {
            PackageManager pm = (PackageManager) getContext().getPackageManager();
            ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
            DevicePolicyManager dpm = (DevicePolicyManager) getContext()
                    .getSystemService(Context.DEVICE_POLICY_SERVICE);

            boolean hasActiveAdmins = dpm.packageHasActiveAdmins(packageName);
            boolean isClearable = (appInfo.flags &
                    (ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA | ApplicationInfo.FLAG_SYSTEM)) !=
                    ApplicationInfo.FLAG_SYSTEM;
            if (!isClearable || hasActiveAdmins) {
                popup.getMenu().findItem(R.id.recent_wipe_app).setEnabled(false);
                popup.getMenu().findItem(R.id.recent_uninstall).setEnabled(false);
            }
        } catch (PackageManager.NameNotFoundException ex) {
        }
        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.recent_remove_item:
                        onTaskViewDismissed(tv);
                        break;
                    case R.id.recent_inspect_item:
                        onTaskViewAppInfoClicked(tv);
                        break;
                    case R.id.recent_force_stop:
                    {
                        ActivityManager am = (ActivityManager) getContext()
                                .getSystemService(Context.ACTIVITY_SERVICE);
                        am.forceStopPackage(packageName);
                        onTaskViewDismissed(tv);
                        break;
                    }
                    case R.id.recent_wipe_app:
                    {
                        ActivityManager am = (ActivityManager) getContext()
                                .getSystemService(Context.ACTIVITY_SERVICE);
                        am.clearApplicationUserData(packageName, new IPackageDataObserver.Stub() {
                            @Override
                            public void onRemoveCompleted(String packageName, boolean succeeded) {}
                        });
                        onTaskViewDismissed(tv);
                        break;
                    }
                    case R.id.recent_uninstall:
                    {
                        Uri packageUri = Uri.parse("package:" + packageName);
                        Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri);
                        uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, true);
                        getContext().startActivity(uninstallIntent);
                        onTaskViewDismissed(tv);
                        break;
                    }
                    default:
                        return false;
                }
                return true;
            }
        });
        popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
            @Override
            public void onDismiss(PopupMenu menu) {
                mPopup = null;
            }
        });
        popup.show();
    }


    @Override
    public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask) {
        // Cancel any doze triggers
+10 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import cyanogenmod.providers.CMSettings;

/* A task view */
public class TaskView extends FrameLayout implements Task.TaskCallbacks,
@@ -43,6 +44,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
    interface TaskViewCallbacks {
        public void onTaskViewAppIconClicked(TaskView tv);
        public void onTaskViewAppInfoClicked(TaskView tv);
        public void onTaskViewLongClicked(TaskView tv);
        public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask);
        public void onTaskViewDismissed(TaskView tv);
        public void onTaskViewClipStateChanged(TaskView tv);
@@ -769,7 +771,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
    public boolean onLongClick(View v) {
        if (v == mHeaderView.mApplicationIcon) {
            if (mCb != null) {
                boolean showDevShortcuts =
                        CMSettings.Secure.getInt(v.getContext().getContentResolver(),
                                CMSettings.Secure.DEVELOPMENT_SHORTCUT, 0) != 0;
                if (showDevShortcuts) {
                    mCb.onTaskViewLongClicked(this);
                } else {
                    mCb.onTaskViewAppInfoClicked(this);
                }
                return true;
            }
        }