ShortcutUser.java revision d99c6f04bbb68f8be78f2c3ca625a3a8d5645275
1/* 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.ComponentName; 21import android.util.ArrayMap; 22import android.util.Slog; 23 24import com.android.internal.util.Preconditions; 25 26import libcore.util.Objects; 27 28import org.xmlpull.v1.XmlPullParser; 29import org.xmlpull.v1.XmlPullParserException; 30import org.xmlpull.v1.XmlSerializer; 31 32import java.io.IOException; 33import java.io.PrintWriter; 34 35/** 36 * User information used by {@link ShortcutService}. 37 */ 38class ShortcutUser { 39 private static final String TAG = ShortcutService.TAG; 40 41 static final String TAG_ROOT = "user"; 42 private static final String TAG_LAUNCHER = "launcher"; 43 44 private static final String ATTR_VALUE = "value"; 45 46 static final class PackageWithUser { 47 final int userId; 48 final String packageName; 49 50 private PackageWithUser(int userId, String packageName) { 51 this.userId = userId; 52 this.packageName = Preconditions.checkNotNull(packageName); 53 } 54 55 public static PackageWithUser of(int launcherUserId, String packageName) { 56 return new PackageWithUser(launcherUserId, packageName); 57 } 58 59 @Override 60 public int hashCode() { 61 return packageName.hashCode() ^ userId; 62 } 63 64 @Override 65 public boolean equals(Object obj) { 66 if (!(obj instanceof PackageWithUser)) { 67 return false; 68 } 69 final PackageWithUser that = (PackageWithUser) obj; 70 71 return userId == that.userId && packageName.equals(that.packageName); 72 } 73 74 @Override 75 public String toString() { 76 return String.format("{Launcher: %d, %s}", userId, packageName); 77 } 78 } 79 80 @UserIdInt 81 final int mUserId; 82 83 private final ArrayMap<String, ShortcutPackage> mPackages = new ArrayMap<>(); 84 85 private final ArrayMap<PackageWithUser, ShortcutLauncher> mLaunchers = new ArrayMap<>(); 86 87 private final ArrayMap<PackageWithUser, ShortcutPackageInfo> mPackageInfos = new ArrayMap<>(); 88 89 private ComponentName mLauncherComponent; 90 91 public ShortcutUser(int userId) { 92 mUserId = userId; 93 } 94 95 public ArrayMap<String, ShortcutPackage> getPackages() { 96 return mPackages; 97 } 98 99 public ArrayMap<PackageWithUser, ShortcutLauncher> getAllLaunchers() { 100 return mLaunchers; 101 } 102 103 public ShortcutLauncher getLauncher(@UserIdInt int userId, @NonNull String packageName) { 104 return mLaunchers.get(PackageWithUser.of(userId, packageName)); 105 } 106 107 public void addLauncher(ShortcutLauncher launcher) { 108 mLaunchers.put(PackageWithUser.of(launcher.getUserId(), launcher.getPackageName()), 109 launcher); 110 } 111 112 public ShortcutLauncher removeLauncher( 113 @UserIdInt int userId, @NonNull String packageName) { 114 return mLaunchers.remove(PackageWithUser.of(userId, packageName)); 115 } 116 117 public ArrayMap<PackageWithUser, ShortcutPackageInfo> getAllPackageInfos() { 118 return mPackageInfos; 119 } 120 121 public ShortcutPackageInfo getPackageInfo(@UserIdInt int userId, @NonNull String packageName) { 122 return mPackageInfos.get(PackageWithUser.of(userId, packageName)); 123 } 124 125 public void addPackageInfo(ShortcutPackageInfo spi) { 126 mPackageInfos.put(PackageWithUser.of(spi.getUserId(), spi.getPackageName()), spi); 127 } 128 129 public ShortcutPackageInfo removePackageInfo( 130 @UserIdInt int userId, @NonNull String packageName) { 131 return mPackageInfos.remove(PackageWithUser.of(userId, packageName)); 132 } 133 134 public ShortcutPackage getPackageShortcuts(@NonNull String packageName) { 135 ShortcutPackage ret = mPackages.get(packageName); 136 if (ret == null) { 137 ret = new ShortcutPackage(mUserId, packageName); 138 mPackages.put(packageName, ret); 139 } 140 return ret; 141 } 142 143 public ShortcutLauncher getLauncherShortcuts(@NonNull String packageName, 144 @UserIdInt int launcherUserId) { 145 final PackageWithUser key = PackageWithUser.of(launcherUserId, packageName); 146 ShortcutLauncher ret = mLaunchers.get(key); 147 if (ret == null) { 148 ret = new ShortcutLauncher(mUserId, packageName, launcherUserId); 149 mLaunchers.put(key, ret); 150 } 151 return ret; 152 } 153 154 public void ensurePackageInfo(ShortcutService s, String packageName, @UserIdInt int userId) { 155 final PackageWithUser key = PackageWithUser.of(userId, packageName); 156 final ShortcutPackageInfo existing = mPackageInfos.get(key); 157 158 if (existing != null) { 159 return; 160 } 161 if (ShortcutService.DEBUG) { 162 Slog.d(TAG, String.format("Fetching package info: %s user=%d", packageName, userId)); 163 } 164 final ShortcutPackageInfo newSpi = ShortcutPackageInfo.generateForInstalledPackage( 165 s, packageName, userId); 166 mPackageInfos.put(key, newSpi); 167 s.scheduleSaveUser(mUserId); 168 } 169 170 public void saveToXml(ShortcutService s, XmlSerializer out, boolean forBackup) 171 throws IOException, XmlPullParserException { 172 out.startTag(null, TAG_ROOT); 173 174 ShortcutService.writeTagValue(out, TAG_LAUNCHER, 175 mLauncherComponent); 176 177 { 178 final int size = mPackageInfos.size(); 179 for (int i = 0; i < size; i++) { 180 saveShortcutPackageItem(s, out, mPackageInfos.valueAt(i), forBackup); 181 } 182 } 183 { 184 final int size = mLaunchers.size(); 185 for (int i = 0; i < size; i++) { 186 saveShortcutPackageItem(s, out, mLaunchers.valueAt(i), forBackup); 187 } 188 } 189 { 190 final int size = mPackages.size(); 191 for (int i = 0; i < size; i++) { 192 saveShortcutPackageItem(s, out, mPackages.valueAt(i), forBackup); 193 } 194 } 195 196 out.endTag(null, TAG_ROOT); 197 } 198 199 private void saveShortcutPackageItem(ShortcutService s, XmlSerializer out, 200 ShortcutPackageItem spi, boolean forBackup) throws IOException, XmlPullParserException { 201 if (forBackup && !s.shouldBackupApp(spi.getPackageName(), mUserId)) { 202 return; // Don't save. 203 } 204 spi.saveToXml(out, forBackup); 205 } 206 207 public static ShortcutUser loadFromXml(XmlPullParser parser, int userId) 208 throws IOException, XmlPullParserException { 209 final ShortcutUser ret = new ShortcutUser(userId); 210 211 final int outerDepth = parser.getDepth(); 212 int type; 213 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 214 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 215 if (type != XmlPullParser.START_TAG) { 216 continue; 217 } 218 final int depth = parser.getDepth(); 219 final String tag = parser.getName(); 220 switch (tag) { 221 case TAG_LAUNCHER: { 222 ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute( 223 parser, ATTR_VALUE); 224 continue; 225 } 226 case ShortcutPackage.TAG_ROOT: { 227 final ShortcutPackage shortcuts = ShortcutPackage.loadFromXml(parser, userId); 228 229 // Don't use addShortcut(), we don't need to save the icon. 230 ret.getPackages().put(shortcuts.getPackageName(), shortcuts); 231 continue; 232 } 233 234 case ShortcutLauncher.TAG_ROOT: { 235 ret.addLauncher(ShortcutLauncher.loadFromXml(parser, userId)); 236 continue; 237 } 238 239 case ShortcutPackageInfo.TAG_ROOT: { 240 ret.addPackageInfo(ShortcutPackageInfo.loadFromXml(parser, userId)); 241 continue; 242 } 243 } 244 throw ShortcutService.throwForInvalidTag(depth, tag); 245 } 246 return ret; 247 } 248 249 public ComponentName getLauncherComponent() { 250 return mLauncherComponent; 251 } 252 253 public void setLauncherComponent(ShortcutService s, ComponentName launcherComponent) { 254 if (Objects.equal(mLauncherComponent, launcherComponent)) { 255 return; 256 } 257 mLauncherComponent = launcherComponent; 258 s.scheduleSaveUser(mUserId); 259 } 260 261 public void resetThrottling() { 262 for (int i = mPackages.size() - 1; i >= 0; i--) { 263 mPackages.valueAt(i).resetThrottling(); 264 } 265 } 266 267 public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) { 268 pw.print(prefix); 269 pw.print("User: "); 270 pw.print(mUserId); 271 pw.println(); 272 273 pw.print(prefix); 274 pw.print(" "); 275 pw.print("Default launcher: "); 276 pw.print(mLauncherComponent); 277 pw.println(); 278 279 for (int i = 0; i < mLaunchers.size(); i++) { 280 mLaunchers.valueAt(i).dump(s, pw, prefix + " "); 281 } 282 283 for (int i = 0; i < mPackages.size(); i++) { 284 mPackages.valueAt(i).dump(s, pw, prefix + " "); 285 } 286 287 for (int i = 0; i < mPackageInfos.size(); i++) { 288 mPackageInfos.valueAt(i).dump(s, pw, prefix + " "); 289 } 290 } 291} 292