1d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk/* 2d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * Copyright (C) 2017 The Android Open Source Project 3d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * 4d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * except in compliance with the License. You may obtain a copy of the License at 6d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * 7d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * http://www.apache.org/licenses/LICENSE-2.0 8d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * 9d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * Unless required by applicable law or agreed to in writing, software distributed under the 10d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * KIND, either express or implied. See the License for the specific language governing 12d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk * permissions and limitations under the License. 13d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk */ 14d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 15d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkpackage com.android.systemui.tuner; 16d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 17d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.ComponentName; 18d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.Context; 19d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.Intent; 20d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.pm.ActivityInfo; 21d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.pm.PackageManager; 22d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.pm.PackageManager.NameNotFoundException; 23d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.res.Resources; 24d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.res.TypedArray; 25d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.content.res.XmlResourceParser; 26d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.graphics.drawable.Icon; 27d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.util.AttributeSet; 28d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport android.util.Xml; 29d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 30d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport com.android.internal.R; 31d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 32d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport org.xmlpull.v1.XmlPullParser; 33d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport org.xmlpull.v1.XmlPullParserException; 34d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 35d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport java.io.IOException; 36d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport java.util.ArrayList; 37d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkimport java.util.List; 38d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 39d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monkpublic class ShortcutParser { 40d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private static final String SHORTCUTS = "android.app.shortcuts"; 41d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private static final String SHORTCUT = "shortcut"; 42d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private static final String INTENT = "intent"; 43d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 44d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private final Context mContext; 45d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private final String mPkg; 46d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private final int mResId; 47d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private final String mName; 48d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private Resources mResources; 49d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private AttributeSet mAttrs; 50d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 51d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public ShortcutParser(Context context, ComponentName component) throws NameNotFoundException { 52d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk this(context, component.getPackageName(), component.getClassName(), 53d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk getResId(context, component)); 54d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 55d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 56d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private static int getResId(Context context, ComponentName component) 57d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk throws NameNotFoundException { 58d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk ActivityInfo i = context.getPackageManager().getActivityInfo( 59d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk component, PackageManager.GET_META_DATA); 60d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk int resId = 0; 61d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (i.metaData != null && i.metaData.containsKey(SHORTCUTS)) { 62d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk resId = i.metaData.getInt(SHORTCUTS); 63d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 64d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk return resId; 65d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 66d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 67d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public ShortcutParser(Context context, String pkg, String name, int resId) { 68d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk mContext = context; 69d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk mPkg = pkg; 70d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk mResId = resId; 71d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk mName = name; 72d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 73d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 74d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public List<Shortcut> getShortcuts() { 75d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk List<Shortcut> list = new ArrayList<>(); 76d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (mResId != 0) { 77d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk try { 78d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk mResources = mContext.getPackageManager().getResourcesForApplication(mPkg); 79d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk XmlResourceParser parser = mResources.getXml(mResId); 80d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk mAttrs = Xml.asAttributeSet(parser); 81d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk int type; 82d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 83d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (type != XmlPullParser.START_TAG) { 84d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk continue; 85d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 86d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (parser.getName().equals(SHORTCUT)) { 87d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk Shortcut c = parseShortcut(parser); 88d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (c != null) { 89d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk list.add(c); 90d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 91d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 92d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 93d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } catch (Exception e) { 94d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk e.printStackTrace(); 95d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 96d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 97d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 98d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk return list; 99d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 100d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 101d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk private Shortcut parseShortcut(XmlResourceParser parser) 102d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk throws IOException, XmlPullParserException { 103d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk final TypedArray sa = mResources.obtainAttributes(mAttrs, R.styleable.Shortcut); 104d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk Shortcut c = new Shortcut(); 105d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 106d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk final boolean enabled = sa.getBoolean(R.styleable.Shortcut_enabled, true); 107d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (!enabled) return null; 108d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk final String id = sa.getString(R.styleable.Shortcut_shortcutId); 109d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk final int iconResId = sa.getResourceId(R.styleable.Shortcut_icon, 0); 110d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk final int titleResId = sa.getResourceId(R.styleable.Shortcut_shortcutShortLabel, 0); 111d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 112d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk c.pkg = mPkg; 113d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk c.icon = Icon.createWithResource(mPkg, iconResId); 114d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk c.id = id; 115d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk c.label = mResources.getString(titleResId); 116d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk c.name = mName; 117d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk int type; 118d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk while ((type = parser.next()) != XmlPullParser.END_TAG) { 119d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (type != XmlPullParser.START_TAG) { 120d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk continue; 121d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 122d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (parser.getName().equals(INTENT)) { 123d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk c.intent = Intent.parseIntent(mResources, parser, mAttrs); 124d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 125d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 126d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk return c.intent != null ? c : null; 127d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 128d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 129d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public static class Shortcut { 130d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public Intent intent; 131d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public String label; 132d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public Icon icon; 133d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public String pkg; 134d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public String id; 135d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public String name; 136d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 137d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public static Shortcut create(Context context, String value) { 138d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk String[] sp = value.split("::"); 139d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk try { 140d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk for (Shortcut shortcut : new ShortcutParser(context, 141d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk new ComponentName(sp[0], sp[1])).getShortcuts()) { 142d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk if (shortcut.id.equals(sp[2])) { 143d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk return shortcut; 144d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 145d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 146d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } catch (NameNotFoundException e) { 147d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 148d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk return null; 149d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 150d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk 151d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk @Override 152d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk public String toString() { 153d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk StringBuilder builder = new StringBuilder(); 154d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk builder.append(pkg); 155d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk builder.append("::"); 156d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk builder.append(name); 157d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk builder.append("::"); 158d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk builder.append(id); 159d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk return builder.toString(); 160d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 161d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk } 162d6fa02f4735d5cd2a72055dee742f998b8e14a0cJason Monk} 163