Loading core/java/android/provider/Settings.java +47 −0 Original line number Diff line number Diff line Loading @@ -56,9 +56,12 @@ import android.util.Log; import com.android.internal.widget.ILockSettings; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.regex.Pattern; /** * The Settings provider contains global system-level device preferences. Loading Loading @@ -3404,6 +3407,44 @@ public final class Settings { MOVED_TO_GLOBAL.add(Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY); } /** * Put a delimited list as a string * @param resolver to access the database with * @param name to store * @param delimiter to split * @param list to join and store * @hide */ public static void putListAsDelimitedString(ContentResolver resolver, String name, String delimiter, List<String> list) { String store = TextUtils.join(delimiter, list); putString(resolver, name, store); } /** * Get a delimited string returned as a list * @param resolver to access the database with * @param name to store * @param delimiter to split the list with * @return list of strings for a specific Settings.Secure item * @hide */ public static List<String> getDelimitedStringAsList(ContentResolver resolver, String name, String delimiter) { String baseString = getString(resolver, name); List<String> list = new ArrayList<String>(); if (!TextUtils.isEmpty(baseString)) { final String[] array = TextUtils.split(baseString, Pattern.quote(delimiter)); for (String item : array) { if (TextUtils.isEmpty(item)) { continue; } list.add(item); } } return list; } /** @hide */ public static void getMovedKeys(HashSet<String> outKeySet) { outKeySet.addAll(MOVED_TO_GLOBAL); Loading Loading @@ -3909,6 +3950,12 @@ public final class Settings { */ public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; /** * Launch actions for left/right lockscreen targets * @hide */ public static final String LOCKSCREEN_TARGETS = "lockscreen_target_actions"; /** * Comma-separated list of location providers that activities may access. Do not rely on * this value being present in settings.db or on ContentObserver notifications on the Loading core/java/com/android/internal/util/cm/LockscreenShortcutsHelper.java 0 → 100644 +210 −0 Original line number Diff line number Diff line package com.android.internal.util.cm; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.ColorFilter; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.Settings; import android.text.TextUtils; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; public class LockscreenShortcutsHelper { public enum Shortcuts { LEFT_SHORTCUT(0), RIGHT_SHORTCUT(1); private final int index; private Shortcuts(int index) { this.index = index; } } public static final String NONE = "none"; private static final String DELIMITER = "|"; private static final String SYSTEM_UI_PKGNAME = "com.android.systemui"; private static final String PHONE_DEFAULT_ICON = "ic_phone_24dp"; private static final String CAMERA_DEFAULT_ICON = "ic_camera_alt_24dp"; private final Context mContext; private OnChangeListener mListener; private List<String> mTargetActivities; public interface OnChangeListener { public void onChange(); } public LockscreenShortcutsHelper(Context context, OnChangeListener listener) { mContext = context; if (listener != null) { mListener = listener; mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.LOCKSCREEN_TARGETS), false, mObserver); } fetchTargets(); } private ContentObserver mObserver = new ContentObserver(null) { @Override public void onChange(boolean selfChange, Uri uri) { fetchTargets(); if (mListener != null) { mListener.onChange(); } } }; public static class TargetInfo { public Drawable icon; public ColorFilter colorFilter; public String uri; public TargetInfo(Drawable icon, ColorFilter colorFilter, String uri) { this.icon = icon; this.colorFilter = colorFilter; this.uri = uri; } } private void fetchTargets() { mTargetActivities = Settings.Secure.getDelimitedStringAsList(mContext.getContentResolver(), Settings.Secure.LOCKSCREEN_TARGETS, DELIMITER); int itemsToPad = Shortcuts.values().length - mTargetActivities.size(); if (itemsToPad > 0) { for (int i = 0; i < itemsToPad; i++) { mTargetActivities.add(NONE); } } } public List<TargetInfo> getDrawablesForTargets() { fetchTargets(); List<TargetInfo> result = new ArrayList<TargetInfo>(); ColorMatrix cm = new ColorMatrix(); cm.setSaturation(0); ColorMatrixColorFilter filter = new ColorMatrixColorFilter(cm); ColorFilter filerToSet = null; for (int i = 0; i < Shortcuts.values().length; i++) { String activity = mTargetActivities.get(i); Drawable drawable = null; if (!TextUtils.isEmpty(activity) && !activity.equals(NONE)) { // No pre-defined action, try to resolve URI try { Intent intent = Intent.parseUri(activity, 0); PackageManager pm = mContext.getPackageManager(); ActivityInfo info = intent.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES); if (info != null) { drawable = info.loadIcon(pm); filerToSet = filter; } } catch (URISyntaxException e) { e.printStackTrace(); // Treat as empty } } if (drawable == null) { drawable = getDrawableFromSystemUI(i == Shortcuts.LEFT_SHORTCUT.index ? PHONE_DEFAULT_ICON : CAMERA_DEFAULT_ICON); filerToSet = null; } result.add(new TargetInfo(drawable, filerToSet, activity)); } return result; } public Drawable getDrawableFromSystemUI(String name) { Resources res = null; Context context = mContext; if (context.getPackageName().equals(SYSTEM_UI_PKGNAME)) { res = context.getResources(); } else { try { context = context.createPackageContext(SYSTEM_UI_PKGNAME, Context.CONTEXT_IGNORE_SECURITY); res = context.getResources(); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } if (res == null) { return null; } int id = res.getIdentifier(name, "drawable", SYSTEM_UI_PKGNAME); if (id > 0) { return res.getDrawable(id); } return null; } private String getFriendlyActivityName(Intent intent, boolean labelOnly) { PackageManager packageManager = mContext.getPackageManager(); ActivityInfo ai = intent.resolveActivityInfo(packageManager, PackageManager.GET_ACTIVITIES); String friendlyName = null; if (ai != null) { friendlyName = ai.loadLabel(packageManager).toString(); if (friendlyName == null && !labelOnly) { friendlyName = ai.name; } } return friendlyName != null || labelOnly ? friendlyName : intent.toUri(0); } private String getFriendlyShortcutName(Intent intent) { String activityName = getFriendlyActivityName(intent, true); String name = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); if (activityName != null && name != null) { return activityName + ": " + name; } return name != null ? name : intent.toUri(0); } public String getFriendlyNameForUri(Shortcuts shortcut) { Intent intent = getIntent(shortcut); if (Intent.ACTION_MAIN.equals(intent.getAction())) { return getFriendlyActivityName(intent, false); } return getFriendlyShortcutName(intent); } public boolean isTargetCustom(Shortcuts shortcut) { return mTargetActivities != null && !mTargetActivities.isEmpty() && !mTargetActivities.get(shortcut.index).equals(NONE); } public Intent getIntent(Shortcuts shortcut) { Intent intent = null; if (isTargetCustom(shortcut)) { try { intent = Intent.parseUri(mTargetActivities.get(shortcut.index), 0); } catch (URISyntaxException e) { e.printStackTrace(); } } return intent; } public void saveTargets(ArrayList<String> targets) { Settings.Secure.putListAsDelimitedString(mContext.getContentResolver(), Settings.Secure.LOCKSCREEN_TARGETS, DELIMITER, targets); } } packages/SystemUI/Android.mk +1 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, src) \ src/com/android/systemui/EventLogTags.logtags LOCAL_STATIC_JAVA_LIBRARIES := Keyguard LOCAL_STATIC_JAVA_LIBRARIES := Keyguard android-support-v7-palette android-support-v4 LOCAL_JAVA_LIBRARIES := telephony-common LOCAL_PACKAGE_NAME := SystemUI Loading packages/SystemUI/res/layout/keyguard_bottom_area.xml +0 −2 Original line number Diff line number Diff line Loading @@ -44,7 +44,6 @@ android:layout_height="@dimen/keyguard_affordance_height" android:layout_width="@dimen/keyguard_affordance_width" android:layout_gravity="bottom|end" android:tint="#ffffffff" android:src="@drawable/ic_camera_alt_24dp" android:scaleType="center" android:contentDescription="@string/accessibility_camera_button" /> Loading @@ -54,7 +53,6 @@ android:layout_height="@dimen/keyguard_affordance_height" android:layout_width="@dimen/keyguard_affordance_width" android:layout_gravity="bottom|start" android:tint="#ffffffff" android:src="@drawable/ic_phone_24dp" android:scaleType="center" android:contentDescription="@string/accessibility_phone_button" /> Loading packages/SystemUI/res/values/cm_strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,7 @@ <string name="stop_notification_dialog_message">Are you sure you want to never show notifications from this application?</string> <string name="left_shortcut_hint">Swipe right for %1$s</string> <string name="right_shortcut_hint">Swipe left for %1$s</string> </resources> Loading
core/java/android/provider/Settings.java +47 −0 Original line number Diff line number Diff line Loading @@ -56,9 +56,12 @@ import android.util.Log; import com.android.internal.widget.ILockSettings; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.regex.Pattern; /** * The Settings provider contains global system-level device preferences. Loading Loading @@ -3404,6 +3407,44 @@ public final class Settings { MOVED_TO_GLOBAL.add(Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY); } /** * Put a delimited list as a string * @param resolver to access the database with * @param name to store * @param delimiter to split * @param list to join and store * @hide */ public static void putListAsDelimitedString(ContentResolver resolver, String name, String delimiter, List<String> list) { String store = TextUtils.join(delimiter, list); putString(resolver, name, store); } /** * Get a delimited string returned as a list * @param resolver to access the database with * @param name to store * @param delimiter to split the list with * @return list of strings for a specific Settings.Secure item * @hide */ public static List<String> getDelimitedStringAsList(ContentResolver resolver, String name, String delimiter) { String baseString = getString(resolver, name); List<String> list = new ArrayList<String>(); if (!TextUtils.isEmpty(baseString)) { final String[] array = TextUtils.split(baseString, Pattern.quote(delimiter)); for (String item : array) { if (TextUtils.isEmpty(item)) { continue; } list.add(item); } } return list; } /** @hide */ public static void getMovedKeys(HashSet<String> outKeySet) { outKeySet.addAll(MOVED_TO_GLOBAL); Loading Loading @@ -3909,6 +3950,12 @@ public final class Settings { */ public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; /** * Launch actions for left/right lockscreen targets * @hide */ public static final String LOCKSCREEN_TARGETS = "lockscreen_target_actions"; /** * Comma-separated list of location providers that activities may access. Do not rely on * this value being present in settings.db or on ContentObserver notifications on the Loading
core/java/com/android/internal/util/cm/LockscreenShortcutsHelper.java 0 → 100644 +210 −0 Original line number Diff line number Diff line package com.android.internal.util.cm; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.ColorFilter; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.Settings; import android.text.TextUtils; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; public class LockscreenShortcutsHelper { public enum Shortcuts { LEFT_SHORTCUT(0), RIGHT_SHORTCUT(1); private final int index; private Shortcuts(int index) { this.index = index; } } public static final String NONE = "none"; private static final String DELIMITER = "|"; private static final String SYSTEM_UI_PKGNAME = "com.android.systemui"; private static final String PHONE_DEFAULT_ICON = "ic_phone_24dp"; private static final String CAMERA_DEFAULT_ICON = "ic_camera_alt_24dp"; private final Context mContext; private OnChangeListener mListener; private List<String> mTargetActivities; public interface OnChangeListener { public void onChange(); } public LockscreenShortcutsHelper(Context context, OnChangeListener listener) { mContext = context; if (listener != null) { mListener = listener; mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.LOCKSCREEN_TARGETS), false, mObserver); } fetchTargets(); } private ContentObserver mObserver = new ContentObserver(null) { @Override public void onChange(boolean selfChange, Uri uri) { fetchTargets(); if (mListener != null) { mListener.onChange(); } } }; public static class TargetInfo { public Drawable icon; public ColorFilter colorFilter; public String uri; public TargetInfo(Drawable icon, ColorFilter colorFilter, String uri) { this.icon = icon; this.colorFilter = colorFilter; this.uri = uri; } } private void fetchTargets() { mTargetActivities = Settings.Secure.getDelimitedStringAsList(mContext.getContentResolver(), Settings.Secure.LOCKSCREEN_TARGETS, DELIMITER); int itemsToPad = Shortcuts.values().length - mTargetActivities.size(); if (itemsToPad > 0) { for (int i = 0; i < itemsToPad; i++) { mTargetActivities.add(NONE); } } } public List<TargetInfo> getDrawablesForTargets() { fetchTargets(); List<TargetInfo> result = new ArrayList<TargetInfo>(); ColorMatrix cm = new ColorMatrix(); cm.setSaturation(0); ColorMatrixColorFilter filter = new ColorMatrixColorFilter(cm); ColorFilter filerToSet = null; for (int i = 0; i < Shortcuts.values().length; i++) { String activity = mTargetActivities.get(i); Drawable drawable = null; if (!TextUtils.isEmpty(activity) && !activity.equals(NONE)) { // No pre-defined action, try to resolve URI try { Intent intent = Intent.parseUri(activity, 0); PackageManager pm = mContext.getPackageManager(); ActivityInfo info = intent.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES); if (info != null) { drawable = info.loadIcon(pm); filerToSet = filter; } } catch (URISyntaxException e) { e.printStackTrace(); // Treat as empty } } if (drawable == null) { drawable = getDrawableFromSystemUI(i == Shortcuts.LEFT_SHORTCUT.index ? PHONE_DEFAULT_ICON : CAMERA_DEFAULT_ICON); filerToSet = null; } result.add(new TargetInfo(drawable, filerToSet, activity)); } return result; } public Drawable getDrawableFromSystemUI(String name) { Resources res = null; Context context = mContext; if (context.getPackageName().equals(SYSTEM_UI_PKGNAME)) { res = context.getResources(); } else { try { context = context.createPackageContext(SYSTEM_UI_PKGNAME, Context.CONTEXT_IGNORE_SECURITY); res = context.getResources(); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } if (res == null) { return null; } int id = res.getIdentifier(name, "drawable", SYSTEM_UI_PKGNAME); if (id > 0) { return res.getDrawable(id); } return null; } private String getFriendlyActivityName(Intent intent, boolean labelOnly) { PackageManager packageManager = mContext.getPackageManager(); ActivityInfo ai = intent.resolveActivityInfo(packageManager, PackageManager.GET_ACTIVITIES); String friendlyName = null; if (ai != null) { friendlyName = ai.loadLabel(packageManager).toString(); if (friendlyName == null && !labelOnly) { friendlyName = ai.name; } } return friendlyName != null || labelOnly ? friendlyName : intent.toUri(0); } private String getFriendlyShortcutName(Intent intent) { String activityName = getFriendlyActivityName(intent, true); String name = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); if (activityName != null && name != null) { return activityName + ": " + name; } return name != null ? name : intent.toUri(0); } public String getFriendlyNameForUri(Shortcuts shortcut) { Intent intent = getIntent(shortcut); if (Intent.ACTION_MAIN.equals(intent.getAction())) { return getFriendlyActivityName(intent, false); } return getFriendlyShortcutName(intent); } public boolean isTargetCustom(Shortcuts shortcut) { return mTargetActivities != null && !mTargetActivities.isEmpty() && !mTargetActivities.get(shortcut.index).equals(NONE); } public Intent getIntent(Shortcuts shortcut) { Intent intent = null; if (isTargetCustom(shortcut)) { try { intent = Intent.parseUri(mTargetActivities.get(shortcut.index), 0); } catch (URISyntaxException e) { e.printStackTrace(); } } return intent; } public void saveTargets(ArrayList<String> targets) { Settings.Secure.putListAsDelimitedString(mContext.getContentResolver(), Settings.Secure.LOCKSCREEN_TARGETS, DELIMITER, targets); } }
packages/SystemUI/Android.mk +1 −1 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, src) \ src/com/android/systemui/EventLogTags.logtags LOCAL_STATIC_JAVA_LIBRARIES := Keyguard LOCAL_STATIC_JAVA_LIBRARIES := Keyguard android-support-v7-palette android-support-v4 LOCAL_JAVA_LIBRARIES := telephony-common LOCAL_PACKAGE_NAME := SystemUI Loading
packages/SystemUI/res/layout/keyguard_bottom_area.xml +0 −2 Original line number Diff line number Diff line Loading @@ -44,7 +44,6 @@ android:layout_height="@dimen/keyguard_affordance_height" android:layout_width="@dimen/keyguard_affordance_width" android:layout_gravity="bottom|end" android:tint="#ffffffff" android:src="@drawable/ic_camera_alt_24dp" android:scaleType="center" android:contentDescription="@string/accessibility_camera_button" /> Loading @@ -54,7 +53,6 @@ android:layout_height="@dimen/keyguard_affordance_height" android:layout_width="@dimen/keyguard_affordance_width" android:layout_gravity="bottom|start" android:tint="#ffffffff" android:src="@drawable/ic_phone_24dp" android:scaleType="center" android:contentDescription="@string/accessibility_phone_button" /> Loading
packages/SystemUI/res/values/cm_strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,7 @@ <string name="stop_notification_dialog_message">Are you sure you want to never show notifications from this application?</string> <string name="left_shortcut_hint">Swipe right for %1$s</string> <string name="right_shortcut_hint">Swipe left for %1$s</string> </resources>