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