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

Commit 3294b6b0 authored by Jim Miller's avatar Jim Miller
Browse files

Fix 6592932: add means to replace assist icon from given package

This provides the means to replace the assist icon shown in keyguard and the
navigation gesture for assist.  It's done by adding metadata called
"com.android.systemui.action_assist_icon" to the activity that handles
android.intent.action.ASSIST.  It should point to a StateListDrawable
in that package with the required states.  For example:

<meta-data android:name="com.android.systemui.action_assist_icon"
    android:resource="@drawable/ic_android_systemui_action_assist" />

And then something like this in drawable/ic_android_systemui_action_assist.xml :

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true"
        android:state_active="false"
        android:state_focused="false"
        android:drawable="@drawable/ic_action_assist_normal" />
    <item android:state_enabled="true"
        android:state_active="true"
        android:state_focused="false"
        android:drawable="@drawable/ic_action_assist_activated" />
    <item android:state_enabled="true"
        android:state_active="false"
        android:state_focused="true"
        android:drawable="@drawable/ic_action_assist_focused" />
</selector>

Change-Id: Ibc29360e179fed68253ff06a07b1bb2b982d0dab
parent ef3a8021
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
@@ -23,12 +23,16 @@ import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -1233,4 +1237,62 @@ public class MultiWaveView extends View {
        }
        return -1;
    }

    private boolean replaceTargetDrawables(Resources res, int existingResourceId,
            int newResourceId) {
        if (existingResourceId == 0 || newResourceId == 0) {
            return false;
        }

        boolean result = false;
        final ArrayList<TargetDrawable> drawables = mTargetDrawables;
        final int size = drawables.size();
        for (int i = 0; i < size; i++) {
            final TargetDrawable target = drawables.get(i);
            if (target != null && target.getResourceId() == existingResourceId) {
                target.setDrawable(res, newResourceId);
                result = true;
            }
        }

        if (result) {
            requestLayout(); // in case any given drawable's size changes
        }

        return result;
    }

    /**
     * Searches the given package for a resource to use to replace the Drawable on the
     * target with the given resource id
     * @param component of the .apk that contains the resource
     * @param name of the metadata in the .apk
     * @param existingResId the resource id of the target to search for
     * @return true if found in the given package and replaced at least one target Drawables
     */
    public boolean replaceTargetDrawablesIfPresent(ComponentName component, String name,
                int existingResId) {
        if (existingResId == 0) return false;

        try {
            PackageManager packageManager = mContext.getPackageManager();
            // Look for the search icon specified in the activity meta-data
            Bundle metaData = packageManager.getActivityInfo(
                    component, PackageManager.GET_META_DATA).metaData;
            if (metaData != null) {
                int iconResId = metaData.getInt(name);
                if (iconResId != 0) {
                    Resources res = packageManager.getResourcesForActivity(component);
                    return replaceTargetDrawables(res, existingResId, iconResId);
                }
            }
        } catch (NameNotFoundException e) {
            Log.w(TAG, "Failed to swap drawable; "
                    + component.flattenToShortString() + " not found", e);
        } catch (Resources.NotFoundException nfe) {
            Log.w(TAG, "Failed to swap drawable from "
                    + component.flattenToShortString(), nfe);
        }
        return false;
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ public class TargetDrawable {
    private float mAlpha = 1.0f;
    private Drawable mDrawable;
    private boolean mEnabled = true;
    private int mResourceId;
    private final int mResourceId;

    /* package */ static class DrawableWithAlpha extends Drawable {
        private float mAlpha = 1.0f;
@@ -78,6 +78,12 @@ public class TargetDrawable {

    public TargetDrawable(Resources res, int resId) {
        mResourceId = resId;
        setDrawable(res, resId);
    }

    public void setDrawable(Resources res, int resId) {
        // Note we explicitly don't set mResourceId to resId since we allow the drawable to be
        // swapped at runtime and want to re-use the existing resource id for identification.
        Drawable drawable = resId == 0 ? null : res.getDrawable(resId);
        // Mutate the drawable so we can animate shared drawable properties.
        mDrawable = drawable != null ? drawable.mutate() : null;
+1 −1
Original line number Diff line number Diff line
@@ -31,6 +31,6 @@
        android:state_enabled="true"
        android:state_active="false"
        android:state_focused="true"
        android:drawable="@drawable/ic_lockscreen_google_activated" />
        android:drawable="@drawable/ic_lockscreen_google_focused" />

</selector>
+17 −0
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ public class SearchPanelView extends FrameLayout implements
    private static final int SEARCH_PANEL_HOLD_DURATION = 500;
    static final String TAG = "SearchPanelView";
    static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
    private static final String ASSIST_ICON_METADATA_NAME =
            "com.android.systemui.action_assist_icon";
    private final Context mContext;
    private BaseStatusBar mBar;
    private StatusBarTouchProxy mStatusBarTouchProxy;
@@ -168,6 +170,21 @@ public class SearchPanelView extends FrameLayout implements
        // TODO: fetch views
        mMultiWaveView = (MultiWaveView) findViewById(R.id.multi_wave_view);
        mMultiWaveView.setOnTriggerListener(mMultiWaveViewListener);
        SearchManager searchManager = getSearchManager();
        if (searchManager != null) {
            ComponentName component = searchManager.getGlobalSearchActivity();
            if (component != null) {
                if (!mMultiWaveView.replaceTargetDrawablesIfPresent(component,
                        ASSIST_ICON_METADATA_NAME,
                        com.android.internal.R.drawable.ic_lockscreen_search)) {
                    Slog.w(TAG, "Couldn't grab icon from component " + component);
                }
            } else {
                Slog.w(TAG, "No search icon specified in component " + component);
            }
        } else {
            Slog.w(TAG, "No SearchManager");
        }
    }

    private boolean pointInside(int x, int y, View v) {
+22 −2
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
    private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
    private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
    private static final String ASSIST_ICON_METADATA_NAME =
            "com.android.systemui.action_assist_icon";

    private LockPatternUtils mLockPatternUtils;
    private KeyguardUpdateMonitor mUpdateMonitor;
@@ -290,8 +292,6 @@ class LockScreen extends LinearLayout implements KeyguardScreen {

        MultiWaveViewMethods(MultiWaveView multiWaveView) {
            mMultiWaveView = multiWaveView;

            // TODO: get search icon.  See Launcher.updateGlobalSearchIcon()
        }

        public boolean isTargetPresent(int resId) {
@@ -310,6 +310,26 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
            if (mMultiWaveView.getTargetResourceId() != resId) {
                mMultiWaveView.setTargetResources(resId);
            }

            // Update the search icon with drawable from the search .apk
            if (!mSearchDisabled) {
                SearchManager searchManager = getSearchManager();
                if (searchManager != null) {
                    ComponentName component = searchManager.getGlobalSearchActivity();
                    if (component != null) {
                        if (!mMultiWaveView.replaceTargetDrawablesIfPresent(component,
                                ASSIST_ICON_METADATA_NAME,
                                com.android.internal.R.drawable.ic_lockscreen_search)) {
                            Slog.w(TAG, "Couldn't grab icon from package " + component);
                        }
                    } else {
                        Slog.w(TAG, "No search icon specified in package " + component);
                    }
                } else {
                    Slog.w(TAG, "No SearchManager");
                }
            }

            setEnabled(com.android.internal.R.drawable.ic_lockscreen_camera, !mCameraDisabled);
            setEnabled(com.android.internal.R.drawable.ic_lockscreen_search, !mSearchDisabled);
        }