blob: 7699f305fb17dde97b16a61a6afd52028bff36c5 [file] [log] [blame]
Makoto Onuki31459242016-03-22 11:12:18 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.pm;
17
18import android.annotation.NonNull;
19import android.annotation.UserIdInt;
20import android.content.pm.ShortcutInfo;
21import android.util.ArrayMap;
22import android.util.ArraySet;
23
24import org.xmlpull.v1.XmlPullParser;
25import org.xmlpull.v1.XmlPullParserException;
26import org.xmlpull.v1.XmlSerializer;
27
28import java.io.IOException;
29import java.io.PrintWriter;
30import java.util.List;
31
32/**
33 * Launcher information used by {@link ShortcutService}.
34 */
Makoto Onuki9da23fc2016-03-29 11:14:42 -070035class ShortcutLauncher extends ShortcutPackageItem {
Makoto Onuki31459242016-03-22 11:12:18 -070036 private static final String TAG = ShortcutService.TAG;
37
38 static final String TAG_ROOT = "launcher-pins";
39
40 private static final String TAG_PACKAGE = "package";
41 private static final String TAG_PIN = "pin";
42
Makoto Onukid99c6f02016-03-28 11:02:54 -070043 private static final String ATTR_LAUNCHER_USER_ID = "launcher-user";
Makoto Onuki31459242016-03-22 11:12:18 -070044 private static final String ATTR_VALUE = "value";
45 private static final String ATTR_PACKAGE_NAME = "package-name";
46
Makoto Onuki9da23fc2016-03-29 11:14:42 -070047 private final int mOwnerUserId;
Makoto Onukid99c6f02016-03-28 11:02:54 -070048
Makoto Onuki31459242016-03-22 11:12:18 -070049 /**
50 * Package name -> IDs.
51 */
52 final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
53
Makoto Onuki9da23fc2016-03-29 11:14:42 -070054 public ShortcutLauncher(@UserIdInt int ownerUserId, @NonNull String packageName,
55 @UserIdInt int launcherUserId, ShortcutPackageInfo spi) {
56 super(launcherUserId, packageName, spi != null ? spi : ShortcutPackageInfo.newEmpty());
57 mOwnerUserId = ownerUserId;
58 }
59
60 public ShortcutLauncher(@UserIdInt int ownerUserId, @NonNull String packageName,
Makoto Onukid99c6f02016-03-28 11:02:54 -070061 @UserIdInt int launcherUserId) {
Makoto Onuki9da23fc2016-03-29 11:14:42 -070062 this(launcherUserId, packageName, launcherUserId, null);
Makoto Onuki31459242016-03-22 11:12:18 -070063 }
64
Makoto Onuki9da23fc2016-03-29 11:14:42 -070065 @Override
66 public int getOwnerUserId() {
67 return mOwnerUserId;
Makoto Onuki0acbb142016-03-22 17:02:57 -070068 }
69
Makoto Onuki9da23fc2016-03-29 11:14:42 -070070 public void pinShortcuts(@NonNull ShortcutService s, @UserIdInt int packageUserId,
71 @NonNull String packageName, @NonNull List<String> ids) {
72 final ShortcutPackage packageShortcuts =
73 s.getPackageShortcutsLocked(packageName, packageUserId);
Makoto Onukid99c6f02016-03-28 11:02:54 -070074
Makoto Onuki31459242016-03-22 11:12:18 -070075 final int idSize = ids.size();
76 if (idSize == 0) {
77 mPinnedShortcuts.remove(packageName);
78 } else {
79 final ArraySet<String> prevSet = mPinnedShortcuts.get(packageName);
80
81 // Pin shortcuts. Make sure only pin the ones that were visible to the caller.
82 // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
83
Makoto Onuki31459242016-03-22 11:12:18 -070084 final ArraySet<String> newSet = new ArraySet<>();
85
86 for (int i = 0; i < idSize; i++) {
87 final String id = ids.get(i);
88 final ShortcutInfo si = packageShortcuts.findShortcutById(id);
89 if (si == null) {
90 continue;
91 }
92 if (si.isDynamic() || (prevSet != null && prevSet.contains(id))) {
93 newSet.add(id);
94 }
95 }
96 mPinnedShortcuts.put(packageName, newSet);
97 }
Makoto Onuki9da23fc2016-03-29 11:14:42 -070098 packageShortcuts.refreshPinnedFlags(s);
Makoto Onuki31459242016-03-22 11:12:18 -070099 }
100
101 /**
102 * Return the pinned shortcut IDs for the publisher package.
103 */
104 public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName) {
105 return mPinnedShortcuts.get(packageName);
106 }
107
108 boolean cleanUpPackage(String packageName) {
109 return mPinnedShortcuts.remove(packageName) != null;
110 }
111
112 /**
113 * Persist.
114 */
Makoto Onuki9da23fc2016-03-29 11:14:42 -0700115 @Override
116 public void saveToXml(XmlSerializer out, boolean forBackup)
117 throws IOException {
Makoto Onuki31459242016-03-22 11:12:18 -0700118 final int size = mPinnedShortcuts.size();
119 if (size == 0) {
120 return; // Nothing to write.
121 }
122
123 out.startTag(null, TAG_ROOT);
Makoto Onuki9da23fc2016-03-29 11:14:42 -0700124 ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, getPackageName());
125 ShortcutService.writeAttr(out, ATTR_LAUNCHER_USER_ID, getPackageUserId());
126 getPackageInfo().saveToXml(out);
Makoto Onuki31459242016-03-22 11:12:18 -0700127
128 for (int i = 0; i < size; i++) {
129 out.startTag(null, TAG_PACKAGE);
130 ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
131 mPinnedShortcuts.keyAt(i));
132
133 final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
134 final int idSize = ids.size();
135 for (int j = 0; j < idSize; j++) {
136 ShortcutService.writeTagValue(out, TAG_PIN, ids.valueAt(j));
137 }
138 out.endTag(null, TAG_PACKAGE);
139 }
140
141 out.endTag(null, TAG_ROOT);
142 }
143
144 /**
145 * Load.
146 */
Makoto Onuki9da23fc2016-03-29 11:14:42 -0700147 public static ShortcutLauncher loadFromXml(XmlPullParser parser, int ownerUserId,
148 boolean fromBackup) throws IOException, XmlPullParserException {
Makoto Onuki31459242016-03-22 11:12:18 -0700149 final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
150 ATTR_PACKAGE_NAME);
Makoto Onuki9da23fc2016-03-29 11:14:42 -0700151
152 // If restoring, just use the real user ID.
153 final int launcherUserId =
154 fromBackup ? ownerUserId
155 : ShortcutService.parseIntAttribute(parser, ATTR_LAUNCHER_USER_ID, ownerUserId);
Makoto Onuki31459242016-03-22 11:12:18 -0700156
Makoto Onukid99c6f02016-03-28 11:02:54 -0700157 final ShortcutLauncher ret = new ShortcutLauncher(launcherUserId, launcherPackageName,
158 launcherUserId);
Makoto Onuki31459242016-03-22 11:12:18 -0700159
Makoto Onuki9da23fc2016-03-29 11:14:42 -0700160 ShortcutPackageInfo spi = null;
161
Makoto Onuki31459242016-03-22 11:12:18 -0700162 ArraySet<String> ids = null;
163 final int outerDepth = parser.getDepth();
164 int type;
165 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
166 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
167 if (type != XmlPullParser.START_TAG) {
168 continue;
169 }
170 final int depth = parser.getDepth();
171 final String tag = parser.getName();
Makoto Onuki9da23fc2016-03-29 11:14:42 -0700172 if (depth == outerDepth + 1) {
173 switch (tag) {
174 case ShortcutPackageInfo.TAG_ROOT:
175 spi = ShortcutPackageInfo.loadFromXml(parser);
176 continue;
177 case TAG_PACKAGE: {
178 final String packageName = ShortcutService.parseStringAttribute(parser,
179 ATTR_PACKAGE_NAME);
180 ids = new ArraySet<>();
181 ret.mPinnedShortcuts.put(packageName, ids);
182 continue;
183 }
Makoto Onuki31459242016-03-22 11:12:18 -0700184 }
185 }
Makoto Onuki9da23fc2016-03-29 11:14:42 -0700186 if (depth == outerDepth + 2) {
187 switch (tag) {
188 case TAG_PIN: {
189 ids.add(ShortcutService.parseStringAttribute(parser,
190 ATTR_VALUE));
191 continue;
192 }
193 }
194 }
195 ShortcutService.warnForInvalidTag(depth, tag);
196 }
197 if (spi != null) {
198 ret.replacePackageInfo(spi);
Makoto Onuki31459242016-03-22 11:12:18 -0700199 }
200 return ret;
201 }
202
203 public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
204 pw.println();
205
206 pw.print(prefix);
207 pw.print("Launcher: ");
Makoto Onuki9da23fc2016-03-29 11:14:42 -0700208 pw.print(getPackageName());
209 pw.print(" Package user: ");
210 pw.print(getPackageUserId());
211 pw.println();
212
213 getPackageInfo().dump(s, pw, prefix + " ");
Makoto Onuki31459242016-03-22 11:12:18 -0700214 pw.println();
215
216 final int size = mPinnedShortcuts.size();
217 for (int i = 0; i < size; i++) {
218 pw.println();
219
220 pw.print(prefix);
221 pw.print(" ");
222 pw.print("Package: ");
223 pw.println(mPinnedShortcuts.keyAt(i));
224
225 final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
226 final int idSize = ids.size();
227
228 for (int j = 0; j < idSize; j++) {
229 pw.print(prefix);
Makoto Onuki0acbb142016-03-22 17:02:57 -0700230 pw.print(" Pinned: ");
Makoto Onuki31459242016-03-22 11:12:18 -0700231 pw.print(ids.valueAt(j));
232 pw.println();
233 }
234 }
235 }
236}