16f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki/* 26f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Copyright (C) 2016 The Android Open Source Project 36f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * 46f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 56f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * you may not use this file except in compliance with the License. 66f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * You may obtain a copy of the License at 76f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * 86f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 96f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * 106f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Unless required by applicable law or agreed to in writing, software 116f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 126f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * See the License for the specific language governing permissions and 146f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * limitations under the License. 156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukipackage com.android.server.pm; 176f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 187001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onukiimport android.annotation.IntDef; 196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.annotation.NonNull; 206f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.annotation.Nullable; 216f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.annotation.UserIdInt; 225504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.app.ActivityManager; 2333525d2f1a8116820f58fc90941cb53bcba54805Makoto Onukiimport android.app.ActivityManagerInternal; 244d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onukiimport android.app.ActivityManagerNative; 250acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onukiimport android.app.AppGlobals; 264d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onukiimport android.app.IUidObserver; 27ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onukiimport android.app.usage.UsageStatsManagerInternal; 284e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onukiimport android.content.BroadcastReceiver; 296f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.ComponentName; 306f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.Context; 316f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.Intent; 324e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onukiimport android.content.IntentFilter; 3322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onukiimport android.content.pm.ActivityInfo; 340acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onukiimport android.content.pm.ApplicationInfo; 350acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onukiimport android.content.pm.IPackageManager; 366f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.IShortcutService; 376f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.LauncherApps; 386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.LauncherApps.ShortcutQuery; 390acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onukiimport android.content.pm.PackageInfo; 406f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.PackageManager; 4120c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onukiimport android.content.pm.PackageManager.NameNotFoundException; 422d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onukiimport android.content.pm.PackageManagerInternal; 436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.ParceledListSlice; 442d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onukiimport android.content.pm.ResolveInfo; 456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.ShortcutInfo; 466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.ShortcutServiceInternal; 476f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.ShortcutServiceInternal.ShortcutChangeListener; 48157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onukiimport android.content.res.Resources; 4922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onukiimport android.content.res.XmlResourceParser; 505504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.graphics.Bitmap; 515504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.graphics.Bitmap.CompressFormat; 525504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.graphics.Canvas; 535504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.graphics.RectF; 546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.graphics.drawable.Icon; 554e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onukiimport android.net.Uri; 566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.Binder; 573366328245621fa6e8fd764a4d3c2f073774d096Makoto Onukiimport android.os.Build; 586f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.Environment; 592e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport android.os.FileUtils; 606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.Handler; 614e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onukiimport android.os.LocaleList; 62aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onukiimport android.os.Looper; 635504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.os.ParcelFileDescriptor; 646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.PersistableBundle; 656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.Process; 666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.RemoteException; 676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.ResultReceiver; 685504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.os.SELinux; 69b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onukiimport android.os.ServiceManager; 706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.ShellCommand; 714d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onukiimport android.os.SystemClock; 726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.os.UserHandle; 73cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onukiimport android.os.UserManager; 746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.text.TextUtils; 756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.text.format.Time; 766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.util.ArraySet; 776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.util.AtomicFile; 784362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onukiimport android.util.KeyValueListParser; 79ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onukiimport android.util.Log; 806f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.util.Slog; 816f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.util.SparseArray; 8202f338e23d06499790c6948709afb1587416eb40Makoto Onukiimport android.util.SparseBooleanArray; 834d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onukiimport android.util.SparseIntArray; 844d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onukiimport android.util.SparseLongArray; 855504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.util.TypedValue; 866f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.util.Xml; 87b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onukiimport android.view.IWindowManager; 886f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.internal.annotations.GuardedBy; 906f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.internal.annotations.VisibleForTesting; 916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.internal.os.BackgroundThread; 926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.internal.util.FastXmlSerializer; 936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.internal.util.Preconditions; 946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.server.LocalServices; 956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.server.SystemService; 96d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onukiimport com.android.server.pm.ShortcutUser.PackageWithUser; 976f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport libcore.io.IoUtils; 996f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 10076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onukiimport org.json.JSONArray; 10176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onukiimport org.json.JSONException; 10276269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onukiimport org.json.JSONObject; 1036f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport org.xmlpull.v1.XmlPullParser; 1046f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport org.xmlpull.v1.XmlPullParserException; 1056f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport org.xmlpull.v1.XmlSerializer; 1066f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1079da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onukiimport java.io.BufferedInputStream; 1089da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onukiimport java.io.BufferedOutputStream; 1099da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onukiimport java.io.ByteArrayInputStream; 1109da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onukiimport java.io.ByteArrayOutputStream; 1116f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.io.File; 1126f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.io.FileDescriptor; 1136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.io.FileInputStream; 1146f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.io.FileNotFoundException; 1156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.io.FileOutputStream; 1166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.io.IOException; 1175504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport java.io.InputStream; 1189da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onukiimport java.io.OutputStream; 1196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.io.PrintWriter; 1207001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onukiimport java.lang.annotation.Retention; 1217001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onukiimport java.lang.annotation.RetentionPolicy; 1226f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.net.URISyntaxException; 1236f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.nio.charset.StandardCharsets; 1246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.util.ArrayList; 12522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onukiimport java.util.Collections; 1266f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.util.List; 127c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onukiimport java.util.concurrent.atomic.AtomicBoolean; 1282e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onukiimport java.util.function.Consumer; 1296f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport java.util.function.Predicate; 1306f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1316f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki/** 1326f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * TODO: 13322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki * - getIconMaxWidth()/getIconMaxHeight() should use xdpi and ydpi. 134b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki * -> But TypedValue.applyDimension() doesn't differentiate x and y..? 1356f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * 136aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki * - Detect when already registered instances are passed to APIs again, which might break 137b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki * internal bitmap handling. 1386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 1396f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukipublic class ShortcutService extends IShortcutService.Stub { 1405504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki static final String TAG = "ShortcutService"; 1416f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1427001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki static final boolean DEBUG = false; // STOPSHIP if true 14341066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static final boolean DEBUG_LOAD = false; // STOPSHIP if true 1444d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki static final boolean DEBUG_PROCSTATE = false; // STOPSHIP if true 1456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1464362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 1474d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day 1484362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 1494362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 1504d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki static final int DEFAULT_MAX_UPDATES_PER_INTERVAL = 10; 1514362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 1524362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 1534362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5; 1544362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 1554362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 1564362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96; 1574362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 1584362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 1594362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki static final int DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP = 48; 1604362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 1614362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 1624362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki static final String DEFAULT_ICON_PERSIST_FORMAT = CompressFormat.PNG.name(); 1634362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 1644362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 1654362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki static final int DEFAULT_ICON_PERSIST_QUALITY = 100; 1666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 167aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki @VisibleForTesting 168aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki static final int DEFAULT_SAVE_DELAY_MS = 3000; 1696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 1716f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki static final String FILENAME_BASE_STATE = "shortcut_service.xml"; 1726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 1746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki static final String DIRECTORY_PER_USER = "shortcut_service"; 1756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 1776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki static final String FILENAME_USER_PACKAGES = "shortcuts.xml"; 1786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1795504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki static final String DIRECTORY_BITMAPS = "bitmaps"; 1806f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 181aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki private static final String TAG_ROOT = "root"; 182aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki private static final String TAG_LAST_RESET_TIME = "last_reset_time"; 183aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 184aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki private static final String ATTR_VALUE = "value"; 1856f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 186b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki private static final String LAUNCHER_INTENT_CATEGORY = Intent.CATEGORY_LAUNCHER; 187b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 18876269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki private static final String KEY_SHORTCUT = "shortcut"; 18976269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki private static final String KEY_LOW_RAM = "lowRam"; 19076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki private static final String KEY_ICON_SIZE = "iconSize"; 19176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 1924362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 1934362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki interface ConfigConstants { 1944362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 195aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki * Key name for the save delay, in milliseconds. (int) 196aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki */ 197aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki String KEY_SAVE_DELAY_MILLIS = "save_delay_ms"; 198aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 199aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki /** 2004362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki * Key name for the throttling reset interval, in seconds. (long) 2014362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 2024362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki String KEY_RESET_INTERVAL_SEC = "reset_interval_sec"; 2034362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 2044362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 2054362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki * Key name for the max number of modifying API calls per app for every interval. (int) 2064362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 207b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki String KEY_MAX_UPDATES_PER_INTERVAL = "max_updates_per_interval"; 2084362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 2094362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 2104362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki * Key name for the max icon dimensions in DP, for non-low-memory devices. 2114362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 2124362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki String KEY_MAX_ICON_DIMENSION_DP = "max_icon_dimension_dp"; 2134362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 2144362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 2154362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki * Key name for the max icon dimensions in DP, for low-memory devices. 2164362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 2174362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki String KEY_MAX_ICON_DIMENSION_DP_LOWRAM = "max_icon_dimension_dp_lowram"; 2184362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 2194362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 2209e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki * Key name for the max dynamic shortcuts per activity. (int) 2214362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 2224362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki String KEY_MAX_SHORTCUTS = "max_shortcuts"; 2234362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 2244362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 22541066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki * Key name for icon compression quality, 0-100. 2264362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 2274362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki String KEY_ICON_QUALITY = "icon_quality"; 2284362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 2294362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 2304362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki * Key name for icon compression format: "PNG", "JPEG" or "WEBP" 2314362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 2324362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki String KEY_ICON_FORMAT = "icon_format"; 2334362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 2344362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 23541066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki final Context mContext; 2366f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2376f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private final Object mLock = new Object(); 2386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 239ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static List<ResolveInfo> EMPTY_RESOLVE_INFO = new ArrayList<>(0); 240ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 241ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static Predicate<ResolveInfo> ACTIVITY_NOT_EXPORTED = 242ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki ri -> !ri.activityInfo.exported; 243ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 244ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static Predicate<PackageInfo> PACKAGE_NOT_INSTALLED = pi -> !isInstalled(pi); 245ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private final Handler mHandler; 2476f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2486f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @GuardedBy("mLock") 2496f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private final ArrayList<ShortcutChangeListener> mListeners = new ArrayList<>(1); 2506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @GuardedBy("mLock") 2526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private long mRawLastResetTime; 2536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 2553f4b1ca97ad7c31bdbe2ba29264841fb58683e81Makoto Onuki * User ID -> UserShortcuts 2566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 2576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @GuardedBy("mLock") 2583145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki private final SparseArray<ShortcutUser> mUsers = new SparseArray<>(); 2596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 261b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki * Max number of dynamic + manifest shortcuts that each application can have at a time. 2626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 263b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki private int mMaxShortcuts; 2646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 266b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki * Max number of updating API calls that each application can make during the interval. 2676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 268b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki int mMaxUpdatesPerInterval; 2696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 2716f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Actual throttling-reset interval. By default it's a day. 2726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 2736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private long mResetInterval; 2746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2755504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki /** 2765504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki * Icon max width/height in pixels. 2775504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki */ 2785504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki private int mMaxIconDimension; 2795504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 2804362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki private CompressFormat mIconPersistFormat; 2814362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki private int mIconPersistQuality; 2825504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 283aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki private int mSaveDelayMillis; 284aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 2850acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki private final IPackageManager mIPackageManager; 2862d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private final PackageManagerInternal mPackageManagerInternal; 287cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki private final UserManager mUserManager; 288ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki private final UsageStatsManagerInternal mUsageStatsManagerInternal; 28933525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki private final ActivityManagerInternal mActivityManagerInternal; 2902d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 291aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki @GuardedBy("mLock") 2924d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki final SparseIntArray mUidState = new SparseIntArray(); 2934d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 2944d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @GuardedBy("mLock") 2954d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki final SparseLongArray mUidLastForegroundElapsedTime = new SparseLongArray(); 2964d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 2974d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @GuardedBy("mLock") 298aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki private List<Integer> mDirtyUserIds = new ArrayList<>(); 299aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 300c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki private final AtomicBoolean mBootCompleted = new AtomicBoolean(); 301c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki 302905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki private static final int PACKAGE_MATCH_FLAGS = 303905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki PackageManager.MATCH_DIRECT_BOOT_AWARE 304b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki | PackageManager.MATCH_DIRECT_BOOT_UNAWARE 305b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki | PackageManager.MATCH_UNINSTALLED_PACKAGES; 306905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki 30702f338e23d06499790c6948709afb1587416eb40Makoto Onuki @GuardedBy("mLock") 30802f338e23d06499790c6948709afb1587416eb40Makoto Onuki final SparseBooleanArray mUnlockedUsers = new SparseBooleanArray(); 30902f338e23d06499790c6948709afb1587416eb40Makoto Onuki 3102e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki // Stats 3112e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @VisibleForTesting 3122e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki interface Stats { 3132e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki int GET_DEFAULT_HOME = 0; 3142e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki int GET_PACKAGE_INFO = 1; 3152e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki int GET_PACKAGE_INFO_WITH_SIG = 2; 3162e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki int GET_APPLICATION_INFO = 3; 3172e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki int LAUNCHER_PERMISSION_CHECK = 4; 3186c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki int CLEANUP_DANGLING_BITMAPS = 5; 319b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki int GET_ACTIVITY_WITH_METADATA = 6; 3206dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki int GET_INSTALLED_PACKAGES = 7; 32122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki int CHECK_PACKAGE_CHANGES = 8; 322157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki int GET_APPLICATION_RESOURCES = 9; 323157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki int RESOURCE_NAME_LOOKUP = 10; 324b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki int GET_LAUNCHER_ACTIVITY = 11; 325b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki int CHECK_LAUNCHER_ACTIVITY = 12; 326ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki int IS_ACTIVITY_ENABLED = 13; 3274e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki int PACKAGE_UPDATE_CHECK = 14; 328085a05cd864252314bcf5c339017a16b68105204Makoto Onuki int ASYNC_PRELOAD_USER_DELAY = 15; 329085a05cd864252314bcf5c339017a16b68105204Makoto Onuki 330085a05cd864252314bcf5c339017a16b68105204Makoto Onuki int COUNT = ASYNC_PRELOAD_USER_DELAY + 1; 331085a05cd864252314bcf5c339017a16b68105204Makoto Onuki } 332085a05cd864252314bcf5c339017a16b68105204Makoto Onuki 333085a05cd864252314bcf5c339017a16b68105204Makoto Onuki private static final String[] STAT_LABELS = { 334085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "getHomeActivities()", 335085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "Launcher permission check", 336085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "getPackageInfo()", 337085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "getPackageInfo(SIG)", 338085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "getApplicationInfo", 339085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "cleanupDanglingBitmaps", 340085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "getActivity+metadata", 341085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "getInstalledPackages", 342085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "checkPackageChanges", 343085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "getApplicationResources", 344085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "resourceNameLookup", 345085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "getLauncherActivity", 346085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "checkLauncherActivity", 347085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "isActivityEnabled", 348085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "packageUpdateCheck", 349085a05cd864252314bcf5c339017a16b68105204Makoto Onuki "asyncPreloadUserDelay" 350085a05cd864252314bcf5c339017a16b68105204Makoto Onuki }; 3512e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 3522e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final Object mStatLock = new Object(); 3532e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 3542e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @GuardedBy("mStatLock") 3552e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki private final int[] mCountStats = new int[Stats.COUNT]; 3562e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 3572e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @GuardedBy("mStatLock") 3582e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki private final long[] mDurationStats = new long[Stats.COUNT]; 3592e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 3604d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki private static final int PROCESS_STATE_FOREGROUND_THRESHOLD = 3614d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; 3624d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 3637001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki static final int OPERATION_SET = 0; 3647001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki static final int OPERATION_ADD = 1; 3657001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki static final int OPERATION_UPDATE = 2; 3667001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 3677001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki /** @hide */ 3687001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki @IntDef(value = { 3697001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki OPERATION_SET, 3707001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki OPERATION_ADD, 3717001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki OPERATION_UPDATE 372b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki }) 3737001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki @Retention(RetentionPolicy.SOURCE) 374b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki @interface ShortcutOperation { 375b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3767001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 377a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki @GuardedBy("mLock") 378a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki private int mWtfCount = 0; 379a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki 380a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki @GuardedBy("mLock") 381a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki private Exception mLastWtfStacktrace; 382a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki 383fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki static class InvalidFileFormatException extends Exception { 384fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki public InvalidFileFormatException(String message, Throwable cause) { 385fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki super(message, cause); 386fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki } 387fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki } 388fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki 3896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public ShortcutService(Context context) { 390ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki this(context, BackgroundThread.get().getLooper(), /*onyForPackgeManagerApis*/ false); 391aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki } 392aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 393aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki @VisibleForTesting 394ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki ShortcutService(Context context, Looper looper, boolean onlyForPackageManagerApis) { 3956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mContext = Preconditions.checkNotNull(context); 3966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki LocalServices.addService(ShortcutServiceInternal.class, new LocalService()); 397aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki mHandler = new Handler(looper); 3980acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki mIPackageManager = AppGlobals.getPackageManager(); 399ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki mPackageManagerInternal = Preconditions.checkNotNull( 400ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki LocalServices.getService(PackageManagerInternal.class)); 401ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki mUserManager = Preconditions.checkNotNull(context.getSystemService(UserManager.class)); 402ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki mUsageStatsManagerInternal = Preconditions.checkNotNull( 403ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki LocalServices.getService(UsageStatsManagerInternal.class)); 40433525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki mActivityManagerInternal = Preconditions.checkNotNull( 40533525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki LocalServices.getService(ActivityManagerInternal.class)); 406cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 407ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (onlyForPackageManagerApis) { 408ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return; // Don't do anything further. For unit tests only. 409ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 410ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 4114e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki // Register receivers. 4124e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki 4134e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki // We need to set a priority, so let's just not use PackageMonitor for now. 4144e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki // TODO Refactor PackageMonitor to support priorities. 4154e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final IntentFilter packageFilter = new IntentFilter(); 4164e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 4174e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 4184e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 4194e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); 4204e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki packageFilter.addDataScheme("package"); 4214e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki packageFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 4224e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki mContext.registerReceiverAsUser(mPackageMonitor, UserHandle.ALL, 4234e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki packageFilter, null, mHandler); 4244e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki 4251030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki final IntentFilter preferedActivityFilter = new IntentFilter(); 4261030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki preferedActivityFilter.addAction(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED); 4271030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki preferedActivityFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 4281030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki mContext.registerReceiverAsUser(mPackageMonitor, UserHandle.ALL, 4291030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki preferedActivityFilter, null, mHandler); 4301030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki 4314e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final IntentFilter localeFilter = new IntentFilter(); 4324e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED); 4334e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki localeFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 4344e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, 4354e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki localeFilter, null, mHandler); 436f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki 4374d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki injectRegisterUidObserver(mUidObserver, ActivityManager.UID_OBSERVER_PROCSTATE 4384d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki | ActivityManager.UID_OBSERVER_GONE); 4396f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 4406f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 4412e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki void logDurationStat(int statId, long start) { 4422e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki synchronized (mStatLock) { 4432e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki mCountStats[statId]++; 4446c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki mDurationStats[statId] += (injectElapsedRealtime() - start); 4452e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 4462e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 4472e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 4484e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki public String injectGetLocaleTagsForUser(@UserIdInt int userId) { 4494e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki // TODO This should get the per-user locale. b/30123329 b/30119489 4504e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki return LocaleList.getDefault().toLanguageTags(); 4514d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4524d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 4534d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki final private IUidObserver mUidObserver = new IUidObserver.Stub() { 454b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki @Override 455b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki public void onUidStateChanged(int uid, int procState) throws RemoteException { 4564d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki handleOnUidStateChanged(uid, procState); 4574d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4584d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 459b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki @Override 460b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki public void onUidGone(int uid) throws RemoteException { 4614d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki handleOnUidStateChanged(uid, ActivityManager.MAX_PROCESS_STATE); 4624d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4634d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 464b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki @Override 465b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki public void onUidActive(int uid) throws RemoteException { 4664d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4674d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 468b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki @Override 469b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki public void onUidIdle(int uid) throws RemoteException { 4704d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4714d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki }; 4724d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 4734d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki void handleOnUidStateChanged(int uid, int procState) { 4744d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki if (DEBUG_PROCSTATE) { 4754d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki Slog.d(TAG, "onUidStateChanged: uid=" + uid + " state=" + procState); 4764d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4774d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki synchronized (mLock) { 4784d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki mUidState.put(uid, procState); 4794d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 4804d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki // We need to keep track of last time an app comes to foreground. 4814d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki // See ShortcutPackage.getApiCallCount() for how it's used. 4824d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki // It doesn't have to be persisted, but it needs to be the elapsed time. 4834d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki if (isProcessStateForeground(procState)) { 4844d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki mUidLastForegroundElapsedTime.put(uid, injectElapsedRealtime()); 4854d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4864d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4874d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4884d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 4894d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki private boolean isProcessStateForeground(int processState) { 49033525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki return (processState != ActivityManager.PROCESS_STATE_NONEXISTENT) 49133525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki && (processState <= PROCESS_STATE_FOREGROUND_THRESHOLD); 4924d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 4934d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 4944d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki boolean isUidForegroundLocked(int uid) { 4954d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki if (uid == Process.SYSTEM_UID) { 4964d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki // IUidObserver doesn't report the state of SYSTEM, but it always has bound services, 4974d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki // so it's foreground anyway. 4984d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki return true; 4994d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 50033525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki // First, check with the local cache. 50133525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki if (isProcessStateForeground(mUidState.get(uid, ActivityManager.MAX_PROCESS_STATE))) { 50233525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki return true; 50333525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki } 50433525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki // If the cache says background, reach out to AM. Since it'll internally need to hold 50533525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki // the AM lock, we use it as a last resort. 50633525d2f1a8116820f58fc90941cb53bcba54805Makoto Onuki return isProcessStateForeground(mActivityManagerInternal.getUidProcessState(uid)); 5074d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 5084d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 5094d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki long getUidLastForegroundElapsedTimeLocked(int uid) { 5104d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki return mUidLastForegroundElapsedTime.get(uid); 5114d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 5124d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 5136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 5146f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * System service lifecycle. 5156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 5166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public static final class Lifecycle extends SystemService { 5176f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final ShortcutService mService; 5186f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 5196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public Lifecycle(Context context) { 5206f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki super(context); 5216f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mService = new ShortcutService(context); 5226f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5236f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 5246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 5256f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void onStart() { 5266f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki publishBinderService(Context.SHORTCUT_SERVICE, mService); 5276f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5286f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 5296f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 5306f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void onBootPhase(int phase) { 5316f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mService.onBootPhase(phase); 5326f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5336f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 5346f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 5356f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void onCleanupUser(int userHandle) { 536cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki mService.handleCleanupUser(userHandle); 5376f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 5396f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 540f3a572b5c0cab23a435bd90414d25de84e00398eMakoto Onuki public void onUnlockUser(int userId) { 541cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki mService.handleUnlockUser(userId); 5426f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 5456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** lifecycle event */ 5466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki void onBootPhase(int phase) { 5476f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (DEBUG) { 5486f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Slog.d(TAG, "onBootPhase: " + phase); 5496f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki switch (phase) { 5516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki case SystemService.PHASE_LOCK_SETTINGS_READY: 5526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki initialize(); 5536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki break; 554c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki case SystemService.PHASE_BOOT_COMPLETED: 555c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki mBootCompleted.set(true); 556c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki break; 5576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5586f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 5606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** lifecycle event */ 561cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki void handleUnlockUser(int userId) { 56222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (DEBUG) { 563085a05cd864252314bcf5c339017a16b68105204Makoto Onuki Slog.d(TAG, "handleUnlockUser: user=" + userId); 56422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 565cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki synchronized (mLock) { 56602f338e23d06499790c6948709afb1587416eb40Makoto Onuki mUnlockedUsers.put(userId, true); 567cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 568085a05cd864252314bcf5c339017a16b68105204Makoto Onuki 569085a05cd864252314bcf5c339017a16b68105204Makoto Onuki // Preload the user data. 570085a05cd864252314bcf5c339017a16b68105204Makoto Onuki // Note, we don't use mHandler here but instead just start a new thread. 571085a05cd864252314bcf5c339017a16b68105204Makoto Onuki // This is because mHandler (which uses com.android.internal.os.BackgroundThread) is very 572085a05cd864252314bcf5c339017a16b68105204Makoto Onuki // busy at this point and this could take hundreds of milliseconds, which would be too 573085a05cd864252314bcf5c339017a16b68105204Makoto Onuki // late since the launcher would already have started. 574085a05cd864252314bcf5c339017a16b68105204Makoto Onuki // So we just create a new thread. This code runs rarely, so we don't use a thread pool 575085a05cd864252314bcf5c339017a16b68105204Makoto Onuki // or anything. 576085a05cd864252314bcf5c339017a16b68105204Makoto Onuki final long start = injectElapsedRealtime(); 577085a05cd864252314bcf5c339017a16b68105204Makoto Onuki injectRunOnNewThread(() -> { 578085a05cd864252314bcf5c339017a16b68105204Makoto Onuki synchronized (mLock) { 579085a05cd864252314bcf5c339017a16b68105204Makoto Onuki logDurationStat(Stats.ASYNC_PRELOAD_USER_DELAY, start); 580085a05cd864252314bcf5c339017a16b68105204Makoto Onuki getUserShortcutsLocked(userId); 581085a05cd864252314bcf5c339017a16b68105204Makoto Onuki } 582085a05cd864252314bcf5c339017a16b68105204Makoto Onuki }); 5836f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 5846f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 5856f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** lifecycle event */ 586cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki void handleCleanupUser(int userId) { 58702f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (DEBUG) { 58802f338e23d06499790c6948709afb1587416eb40Makoto Onuki Slog.d(TAG, "handleCleanupUser: user=" + userId); 58902f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 590cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki synchronized (mLock) { 591cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki unloadUserLocked(userId); 59202f338e23d06499790c6948709afb1587416eb40Makoto Onuki 59302f338e23d06499790c6948709afb1587416eb40Makoto Onuki mUnlockedUsers.put(userId, false); 594cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 595cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 596cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 597cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki private void unloadUserLocked(int userId) { 598cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki if (DEBUG) { 599cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki Slog.d(TAG, "unloadUserLocked: user=" + userId); 600cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 601aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki // Save all dirty information. 602aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki saveDirtyInfo(); 603aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 6046f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Unload 6053f4b1ca97ad7c31bdbe2ba29264841fb58683e81Makoto Onuki mUsers.delete(userId); 6066f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 6076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 6086f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** Return the base state file name */ 6096f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private AtomicFile getBaseStateFile() { 6106f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final File path = new File(injectSystemDataPath(), FILENAME_BASE_STATE); 6116f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki path.mkdirs(); 6126f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return new AtomicFile(path); 6136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 6146f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 6156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 6166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Init the instance. (load the state file, etc) 6176f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 6186f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private void initialize() { 6196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 6204362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki loadConfigurationLocked(); 6216f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki loadBaseStateLocked(); 6226f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 6236f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 6246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 6254362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 6264362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki * Load the configuration from Settings. 6274362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 6284362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki private void loadConfigurationLocked() { 6294362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki updateConfigurationLocked(injectShortcutManagerConstants()); 6304362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 6314362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6324362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki /** 6334362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki * Load the configuration from Settings. 6344362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki */ 6354362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 6364362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki boolean updateConfigurationLocked(String config) { 6374362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki boolean result = true; 6384362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6394362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki final KeyValueListParser parser = new KeyValueListParser(','); 6404362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki try { 6414362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki parser.setString(config); 6424362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } catch (IllegalArgumentException e) { 6434362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki // Failed to parse the settings string, log this and move on 6444362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki // with defaults. 6454362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki Slog.e(TAG, "Bad shortcut manager settings", e); 6464362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki result = false; 6474362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 6484362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6495ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki mSaveDelayMillis = Math.max(0, (int) parser.getLong(ConfigConstants.KEY_SAVE_DELAY_MILLIS, 6505ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki DEFAULT_SAVE_DELAY_MS)); 651aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 6525ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki mResetInterval = Math.max(1, parser.getLong( 6534362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC) 6545ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki * 1000L); 6554362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 656b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki mMaxUpdatesPerInterval = Math.max(0, (int) parser.getLong( 657b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL, DEFAULT_MAX_UPDATES_PER_INTERVAL)); 6584362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 659b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki mMaxShortcuts = Math.max(0, (int) parser.getLong( 6605ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP)); 6614362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6625ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki final int iconDimensionDp = Math.max(1, injectIsLowRamDevice() 6634362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki ? (int) parser.getLong( 664b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM, 665b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP) 6664362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki : (int) parser.getLong( 667b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki ConfigConstants.KEY_MAX_ICON_DIMENSION_DP, 668b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki DEFAULT_MAX_ICON_DIMENSION_DP)); 6694362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6704362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki mMaxIconDimension = injectDipToPixel(iconDimensionDp); 6714362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6724362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki mIconPersistFormat = CompressFormat.valueOf( 6734362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki parser.getString(ConfigConstants.KEY_ICON_FORMAT, DEFAULT_ICON_PERSIST_FORMAT)); 6744362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6754362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki mIconPersistQuality = (int) parser.getLong( 6764362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki ConfigConstants.KEY_ICON_QUALITY, 6774362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki DEFAULT_ICON_PERSIST_QUALITY); 6784362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6794362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki return result; 6804362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 6814362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 6826f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 6834362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki String injectShortcutManagerConstants() { 6844362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki return android.provider.Settings.Global.getString( 6854362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki mContext.getContentResolver(), 6864362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki android.provider.Settings.Global.SHORTCUT_MANAGER_CONSTANTS); 6874362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 6885504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 6894362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 6904362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki int injectDipToPixel(int dip) { 6914362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, 6924362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki mContext.getResources().getDisplayMetrics()); 6936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 6946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 6955504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // === Persisting === 6966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 6976f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Nullable 69841066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static String parseStringAttribute(XmlPullParser parser, String attribute) { 6996f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return parser.getAttributeValue(null, attribute); 7006f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7016f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 7020acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki static boolean parseBooleanAttribute(XmlPullParser parser, String attribute) { 7030acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki return parseLongAttribute(parser, attribute) == 1; 7040acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 7050acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 70641066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static int parseIntAttribute(XmlPullParser parser, String attribute) { 70741066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki return (int) parseLongAttribute(parser, attribute); 70841066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki } 70941066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki 710d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki static int parseIntAttribute(XmlPullParser parser, String attribute, int def) { 711d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return (int) parseLongAttribute(parser, attribute, def); 712d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 713d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 71441066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static long parseLongAttribute(XmlPullParser parser, String attribute) { 715d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return parseLongAttribute(parser, attribute, 0); 716d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 717d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 718d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki static long parseLongAttribute(XmlPullParser parser, String attribute, long def) { 7196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final String value = parseStringAttribute(parser, attribute); 7206f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (TextUtils.isEmpty(value)) { 721d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return def; 7226f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7236f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki try { 7246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return Long.parseLong(value); 7256f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } catch (NumberFormatException e) { 7266f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Slog.e(TAG, "Error parsing long " + value); 727d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return def; 7286f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7296f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7306f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 7316f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Nullable 73241066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static ComponentName parseComponentNameAttribute(XmlPullParser parser, String attribute) { 7336f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final String value = parseStringAttribute(parser, attribute); 7346f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (TextUtils.isEmpty(value)) { 7356f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return null; 7366f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7376f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return ComponentName.unflattenFromString(value); 7386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7396f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 7406f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Nullable 741440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki static Intent parseIntentAttributeNoDefault(XmlPullParser parser, String attribute) { 7426f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final String value = parseStringAttribute(parser, attribute); 743b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki Intent parsed = null; 744b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki if (!TextUtils.isEmpty(value)) { 745b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki try { 746b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki parsed = Intent.parseUri(value, /* flags =*/ 0); 747b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki } catch (URISyntaxException e) { 748b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki Slog.e(TAG, "Error parsing intent", e); 749b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki } 7506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 751440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki return parsed; 752440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki } 753440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki 754440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki @Nullable 755440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki static Intent parseIntentAttribute(XmlPullParser parser, String attribute) { 756440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki Intent parsed = parseIntentAttributeNoDefault(parser, attribute); 757b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki if (parsed == null) { 758b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki // Default intent. 759b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki parsed = new Intent(Intent.ACTION_VIEW); 7606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 761b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki return parsed; 7626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7636f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 76441066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static void writeTagValue(XmlSerializer out, String tag, String value) throws IOException { 7656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (TextUtils.isEmpty(value)) return; 7666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 7676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.startTag(null, tag); 7686f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.attribute(null, ATTR_VALUE, value); 7696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.endTag(null, tag); 7706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7716f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 77241066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static void writeTagValue(XmlSerializer out, String tag, long value) throws IOException { 7736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki writeTagValue(out, tag, Long.toString(value)); 7746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 7762d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki static void writeTagValue(XmlSerializer out, String tag, ComponentName name) throws IOException { 7772d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (name == null) return; 7782d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki writeTagValue(out, tag, name.flattenToString()); 7792d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 7802d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 78141066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static void writeTagExtra(XmlSerializer out, String tag, PersistableBundle bundle) 7826f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki throws IOException, XmlPullParserException { 7836f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (bundle == null) return; 7846f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 7856f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.startTag(null, tag); 7866f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki bundle.saveToXml(out); 7876f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.endTag(null, tag); 7886f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 79022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki static void writeAttr(XmlSerializer out, String name, CharSequence value) throws IOException { 7916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (TextUtils.isEmpty(value)) return; 7926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 79322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki out.attribute(null, name, value.toString()); 7946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 79641066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static void writeAttr(XmlSerializer out, String name, long value) throws IOException { 7976f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki writeAttr(out, name, String.valueOf(value)); 7986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 7996f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8000acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki static void writeAttr(XmlSerializer out, String name, boolean value) throws IOException { 8010acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki if (value) { 8020acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki writeAttr(out, name, "1"); 8030acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 8040acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 8050acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 80641066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static void writeAttr(XmlSerializer out, String name, ComponentName comp) throws IOException { 8076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (comp == null) return; 8086f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki writeAttr(out, name, comp.flattenToString()); 8096f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8106f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 81141066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static void writeAttr(XmlSerializer out, String name, Intent intent) throws IOException { 8126f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (intent == null) return; 8136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8146f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki writeAttr(out, name, intent.toUri(/* flags =*/ 0)); 8156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8176f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 8186f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki void saveBaseStateLocked() { 8196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final AtomicFile file = getBaseStateFile(); 8206f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (DEBUG) { 821aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki Slog.d(TAG, "Saving to " + file.getBaseFile()); 8226f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8236f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki FileOutputStream outs = null; 8256f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki try { 8266f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki outs = file.startWrite(); 8276f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8286f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Write to XML 8296f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki XmlSerializer out = new FastXmlSerializer(); 8306f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.setOutput(outs, StandardCharsets.UTF_8.name()); 8316f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.startDocument(null, true); 8326f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.startTag(null, TAG_ROOT); 8336f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8346f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Body. 8356f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki writeTagValue(out, TAG_LAST_RESET_TIME, mRawLastResetTime); 8366f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8376f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Epilogue. 8386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.endTag(null, TAG_ROOT); 8396f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki out.endDocument(); 8406f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8416f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Close. 8426f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki file.finishWrite(outs); 8436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } catch (IOException e) { 8446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e); 8456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki file.failWrite(outs); 8466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8476f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8486f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8496f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private void loadBaseStateLocked() { 8506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mRawLastResetTime = 0; 8516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final AtomicFile file = getBaseStateFile(); 8536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (DEBUG) { 854aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki Slog.d(TAG, "Loading from " + file.getBaseFile()); 8556f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki try (FileInputStream in = file.openRead()) { 8576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki XmlPullParser parser = Xml.newPullParser(); 8586f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki parser.setInput(in, StandardCharsets.UTF_8.name()); 8596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki int type; 8616f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 8626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (type != XmlPullParser.START_TAG) { 8636f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki continue; 8646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final int depth = parser.getDepth(); 8666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Check the root tag 8676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final String tag = parser.getName(); 8686f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (depth == 1) { 8696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (!TAG_ROOT.equals(tag)) { 8706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Slog.e(TAG, "Invalid root tag: " + tag); 8716f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return; 8726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki continue; 8746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Assume depth == 2 8766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki switch (tag) { 8776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki case TAG_LAST_RESET_TIME: 8786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mRawLastResetTime = parseLongAttribute(parser, ATTR_VALUE); 8796f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki break; 8806f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki default: 8816f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Slog.e(TAG, "Invalid tag: " + tag); 8826f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki break; 8836f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8846f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8856f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } catch (FileNotFoundException e) { 8866f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Use the default 887b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } catch (IOException | XmlPullParserException e) { 8886f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e); 8896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8906f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mRawLastResetTime = 0; 8916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Adjust the last reset time. 8936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki getLastResetTimeLocked(); 8946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 8960eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki @VisibleForTesting 8970eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki final File getUserFile(@UserIdInt int userId) { 8980eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES); 8990eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki } 9000eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki 9016f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private void saveUserLocked(@UserIdInt int userId) { 9020eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki final File path = getUserFile(userId); 9036f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (DEBUG) { 904aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki Slog.d(TAG, "Saving to " + path); 9056f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9060eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki path.getParentFile().mkdirs(); 9076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final AtomicFile file = new AtomicFile(path); 9089da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki FileOutputStream os = null; 9096f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki try { 9109da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki os = file.startWrite(); 9116f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 9129da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki saveUserInternalLocked(userId, os, /* forBackup= */ false); 9136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 9149da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki file.finishWrite(os); 9151e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki 9161e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // Remove all dangling bitmap files. 9171e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki cleanupDanglingBitmapDirectoriesLocked(userId); 918b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } catch (XmlPullParserException | IOException e) { 9196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e); 9209da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki file.failWrite(os); 9216f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9226f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9236f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 9249da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki private void saveUserInternalLocked(@UserIdInt int userId, OutputStream os, 9259da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki boolean forBackup) throws IOException, XmlPullParserException { 9269da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9279da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final BufferedOutputStream bos = new BufferedOutputStream(os); 9289da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9299da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki // Write to XML 9309da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki XmlSerializer out = new FastXmlSerializer(); 9319da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki out.setOutput(bos, StandardCharsets.UTF_8.name()); 9329da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki out.startDocument(null, true); 9339da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 934c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki getUserShortcutsLocked(userId).saveToXml(out, forBackup); 9359da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9369da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki out.endDocument(); 9379da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9389da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki bos.flush(); 9399da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki os.flush(); 9409da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 9419da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 94241066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static IOException throwForInvalidTag(int depth, String tag) throws IOException { 9436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki throw new IOException(String.format("Invalid tag '%s' found at depth %d", tag, depth)); 9446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 9469da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki static void warnForInvalidTag(int depth, String tag) throws IOException { 9479da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki Slog.w(TAG, String.format("Invalid tag '%s' found at depth %d", tag, depth)); 9489da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 9499da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Nullable 9513145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki private ShortcutUser loadUserLocked(@UserIdInt int userId) { 9520eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki final File path = getUserFile(userId); 9536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (DEBUG) { 954aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki Slog.d(TAG, "Loading from " + path); 9556f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final AtomicFile file = new AtomicFile(path); 9576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 9586f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final FileInputStream in; 9596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki try { 9606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki in = file.openRead(); 9616f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } catch (FileNotFoundException e) { 9626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (DEBUG) { 963aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki Slog.d(TAG, "Not found " + path); 9646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return null; 9666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki try { 968b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false); 9696c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki return ret; 970fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki } catch (IOException | XmlPullParserException | InvalidFileFormatException e) { 9716f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e); 9726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return null; 9736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } finally { 9746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki IoUtils.closeQuietly(in); 9756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 9776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 9789da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki private ShortcutUser loadUserInternal(@UserIdInt int userId, InputStream is, 979fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki boolean fromBackup) throws XmlPullParserException, IOException, 980fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki InvalidFileFormatException { 9819da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9829da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final BufferedInputStream bis = new BufferedInputStream(is); 9839da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9849da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki ShortcutUser ret = null; 9859da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki XmlPullParser parser = Xml.newPullParser(); 9869da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki parser.setInput(bis, StandardCharsets.UTF_8.name()); 9879da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9889da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki int type; 9899da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 9909da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki if (type != XmlPullParser.START_TAG) { 9919da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki continue; 9929da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 9939da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final int depth = parser.getDepth(); 9949da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 9959da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final String tag = parser.getName(); 9969da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki if (DEBUG_LOAD) { 9979da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki Slog.d(TAG, String.format("depth=%d type=%d name=%s", 9989da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki depth, type, tag)); 9999da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 10009da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki if ((depth == 1) && ShortcutUser.TAG_ROOT.equals(tag)) { 10019da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki ret = ShortcutUser.loadFromXml(this, parser, userId, fromBackup); 10029da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki continue; 10039da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 10049da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki throwForInvalidTag(depth, tag); 10059da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 10069da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki return ret; 10079da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 10089da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 10096f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private void scheduleSaveBaseState() { 10100acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki scheduleSaveInner(UserHandle.USER_NULL); // Special case -- use USER_NULL for base state. 1011aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki } 1012aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 1013aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki void scheduleSaveUser(@UserIdInt int userId) { 10140acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki scheduleSaveInner(userId); 1015aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki } 1016aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 1017aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki // In order to re-schedule, we need to reuse the same instance, so keep it in final. 1018aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki private final Runnable mSaveDirtyInfoRunner = this::saveDirtyInfo; 1019aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki 10200acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki private void scheduleSaveInner(@UserIdInt int userId) { 1021aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki if (DEBUG) { 1022aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki Slog.d(TAG, "Scheduling to save for " + userId); 1023aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki } 10246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 1025aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki if (!mDirtyUserIds.contains(userId)) { 1026aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki mDirtyUserIds.add(userId); 1027aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki } 10286f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 1029aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki // If already scheduled, remove that and re-schedule in N seconds. 1030aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki mHandler.removeCallbacks(mSaveDirtyInfoRunner); 1031aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki mHandler.postDelayed(mSaveDirtyInfoRunner, mSaveDelayMillis); 10326f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 10336f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1034aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki @VisibleForTesting 1035aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki void saveDirtyInfo() { 1036aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki if (DEBUG) { 1037aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki Slog.d(TAG, "saveDirtyInfo"); 1038aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki } 103902f338e23d06499790c6948709afb1587416eb40Makoto Onuki try { 104002f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 104102f338e23d06499790c6948709afb1587416eb40Makoto Onuki for (int i = mDirtyUserIds.size() - 1; i >= 0; i--) { 104202f338e23d06499790c6948709afb1587416eb40Makoto Onuki final int userId = mDirtyUserIds.get(i); 104302f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (userId == UserHandle.USER_NULL) { // USER_NULL for base state. 104402f338e23d06499790c6948709afb1587416eb40Makoto Onuki saveBaseStateLocked(); 104502f338e23d06499790c6948709afb1587416eb40Makoto Onuki } else { 104602f338e23d06499790c6948709afb1587416eb40Makoto Onuki saveUserLocked(userId); 104702f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 1048aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki } 104902f338e23d06499790c6948709afb1587416eb40Makoto Onuki mDirtyUserIds.clear(); 1050aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki } 105102f338e23d06499790c6948709afb1587416eb40Makoto Onuki } catch (Exception e) { 105202f338e23d06499790c6948709afb1587416eb40Makoto Onuki wtf("Exception in saveDirtyInfo", e); 10536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 10546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 10556f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 10566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** Return the last reset time. */ 10576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki long getLastResetTimeLocked() { 1058aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki updateTimesLocked(); 10596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return mRawLastResetTime; 10606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 10616f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 10626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** Return the next reset time. */ 10636f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki long getNextResetTimeLocked() { 1064aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki updateTimesLocked(); 10656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return mRawLastResetTime + mResetInterval; 10666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 10676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 10684554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki static boolean isClockValid(long time) { 10694554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki return time >= 1420070400; // Thu, 01 Jan 2015 00:00:00 GMT 10704554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki } 10714554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki 10726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 10736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Update the last reset time. 10746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 1075aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki private void updateTimesLocked() { 10766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 10776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final long now = injectCurrentTimeMillis(); 10786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 10796f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final long prevLastResetTime = mRawLastResetTime; 10806f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 10816f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (mRawLastResetTime == 0) { // first launch. 10826f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // TODO Randomize?? 10836f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mRawLastResetTime = now; 10846f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } else if (now < mRawLastResetTime) { 10856f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Clock rewound. 10864554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki if (isClockValid(now)) { 1087aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki Slog.w(TAG, "Clock rewound"); 10884554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki // TODO Randomize?? 10894554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki mRawLastResetTime = now; 10904554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki } 10916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } else { 1092aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki if ((mRawLastResetTime + mResetInterval) <= now) { 1093aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki final long offset = mRawLastResetTime % mResetInterval; 1094aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki mRawLastResetTime = ((now / mResetInterval) * mResetInterval) + offset; 10956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 10966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 10976f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (prevLastResetTime != mRawLastResetTime) { 10986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki scheduleSaveBaseState(); 10996f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 11006f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 11016f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 11021e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // Requires mLock held, but "Locked" prefix would look weired so we just say "L". 110302f338e23d06499790c6948709afb1587416eb40Makoto Onuki protected boolean isUserUnlockedL(@UserIdInt int userId) { 11041e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // First, check the local copy. 11051e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki if (mUnlockedUsers.get(userId)) { 11061e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki return true; 11071e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki } 11081e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // If the local copy says the user is locked, check with AM for the actual state, since 11091e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // the user might just have been unlocked. 11101e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // Note we just don't use isUserUnlockingOrUnlocked() here, because it'll return false 11111e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // when the user is STOPPING, which we still want to consider as "unlocked". 11121e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki final long token = injectClearCallingIdentity(); 11131e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki try { 11141e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki return mUserManager.isUserUnlockingOrUnlocked(userId); 11151e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki } finally { 11161e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki injectRestoreCallingIdentity(token); 11171e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki } 11189c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki } 11199c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki 112002f338e23d06499790c6948709afb1587416eb40Makoto Onuki // Requires mLock held, but "Locked" prefix would look weired so we jsut say "L". 112102f338e23d06499790c6948709afb1587416eb40Makoto Onuki void throwIfUserLockedL(@UserIdInt int userId) { 112202f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(userId)) { 11239c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki throw new IllegalStateException("User " + userId + " is locked or not running"); 11249c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki } 11259c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki } 11269c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki 1127cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki @GuardedBy("mLock") 1128cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki @NonNull 11292e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki private boolean isUserLoadedLocked(@UserIdInt int userId) { 1130cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki return mUsers.get(userId) != null; 1131cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 1132cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 11336f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** Return the per-user state. */ 11346f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @GuardedBy("mLock") 11356f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @NonNull 11363145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki ShortcutUser getUserShortcutsLocked(@UserIdInt int userId) { 113702f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(userId)) { 11389c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki wtf("User still locked"); 11399c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki } 11409c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki 11413145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki ShortcutUser userPackages = mUsers.get(userId); 11426f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (userPackages == null) { 11436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki userPackages = loadUserLocked(userId); 11446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (userPackages == null) { 1145c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki userPackages = new ShortcutUser(this, userId); 11466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 11473f4b1ca97ad7c31bdbe2ba29264841fb58683e81Makoto Onuki mUsers.put(userId, userPackages); 1148085a05cd864252314bcf5c339017a16b68105204Makoto Onuki 1149085a05cd864252314bcf5c339017a16b68105204Makoto Onuki // Also when a user's data is first accessed, scan all packages. 1150085a05cd864252314bcf5c339017a16b68105204Makoto Onuki checkPackageChanges(userId); 11516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 11526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return userPackages; 11536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 11546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 11552e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki void forEachLoadedUserLocked(@NonNull Consumer<ShortcutUser> c) { 11562e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki for (int i = mUsers.size() - 1; i >= 0; i--) { 11572e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki c.accept(mUsers.valueAt(i)); 11582e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 11592e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 11602e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 1161c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki /** 1162c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki * Return the per-user per-package state. If the caller is a publisher, use 1163c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki * {@link #getPackageShortcutsForPublisherLocked} instead. 1164c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki */ 11656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @GuardedBy("mLock") 11666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @NonNull 11673145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki ShortcutPackage getPackageShortcutsLocked( 11686f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @NonNull String packageName, @UserIdInt int userId) { 1169c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki return getUserShortcutsLocked(userId).getPackageShortcuts(packageName); 1170de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki } 1171de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki 1172c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki /** Return the per-user per-package state. Use this when the caller is a publisher. */ 1173c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki @GuardedBy("mLock") 1174c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki @NonNull 1175c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki ShortcutPackage getPackageShortcutsForPublisherLocked( 1176c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki @NonNull String packageName, @UserIdInt int userId) { 1177c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ret = getUserShortcutsLocked(userId).getPackageShortcuts(packageName); 1178c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki ret.getUser().onCalledByPublisher(packageName); 1179c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki return ret; 1180c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki } 1181c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki 1182de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki @GuardedBy("mLock") 1183de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki @NonNull 11842e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki ShortcutLauncher getLauncherShortcutsLocked( 11852e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @NonNull String packageName, @UserIdInt int ownerUserId, 11862e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki @UserIdInt int launcherUserId) { 11872e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki return getUserShortcutsLocked(ownerUserId) 1188c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .getLauncherShortcuts(packageName, launcherUserId); 11896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 11906f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 11916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // === Caller validation === 11926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 11935504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki void removeIcon(@UserIdInt int userId, ShortcutInfo shortcut) { 11941e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // Do not remove the actual bitmap file yet, because if the device crashes before saving 11951e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki // he XML we'd lose the icon. We just remove all dangling files after saving the XML. 1196dd097812fa84b898a46cb5dd253422e78779a150Makoto Onuki shortcut.setIconResourceId(0); 1197dd097812fa84b898a46cb5dd253422e78779a150Makoto Onuki shortcut.setIconResName(null); 1198dd097812fa84b898a46cb5dd253422e78779a150Makoto Onuki shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES); 11995504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 12005504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 12010033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki public void cleanupBitmapsForPackage(@UserIdInt int userId, String packageName) { 12020033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki final File packagePath = new File(getUserBitmapFilePath(userId), packageName); 12030033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki if (!packagePath.isDirectory()) { 12040033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki return; 12050033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki } 12060033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki if (!(FileUtils.deleteContents(packagePath) && packagePath.delete())) { 12070033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki Slog.w(TAG, "Unable to remove directory " + packagePath); 12080033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki } 12090033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki } 12100033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki 12111e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki private void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) { 12126c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (DEBUG) { 12136c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki Slog.d(TAG, "cleanupDanglingBitmaps: userId=" + userId); 12146c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12156c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final long start = injectElapsedRealtime(); 12166c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki 12171e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki final ShortcutUser user = getUserShortcutsLocked(userId); 12181e1732399a48c9521eea7a117f1f0e87ca64d2abMakoto Onuki 12196c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final File bitmapDir = getUserBitmapFilePath(userId); 12206c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final File[] children = bitmapDir.listFiles(); 12216c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (children == null) { 12226c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki return; 12236c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12246c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki for (File child : children) { 12256c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (!child.isDirectory()) { 12266c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki continue; 12276c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12286c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final String packageName = child.getName(); 12296c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (DEBUG) { 12306c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki Slog.d(TAG, "cleanupDanglingBitmaps: Found directory=" + packageName); 12316c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12326c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (!user.hasPackage(packageName)) { 12336c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (DEBUG) { 12346c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki Slog.d(TAG, "Removing dangling bitmap directory: " + packageName); 12356c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12366c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki cleanupBitmapsForPackage(userId, packageName); 12376c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } else { 12386c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki cleanupDanglingBitmapFilesLocked(userId, user, packageName, child); 12396c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12406c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12416c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki logDurationStat(Stats.CLEANUP_DANGLING_BITMAPS, start); 12426c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12436c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki 12446c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki private void cleanupDanglingBitmapFilesLocked(@UserIdInt int userId, @NonNull ShortcutUser user, 12456c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki @NonNull String packageName, @NonNull File path) { 12466c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final ArraySet<String> usedFiles = 1247c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki user.getPackageShortcuts(packageName).getUsedBitmapFiles(); 12486c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki 12496c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki for (File child : path.listFiles()) { 12506c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (!child.isFile()) { 12516c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki continue; 12526c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12536c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final String name = child.getName(); 12546c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (!usedFiles.contains(name)) { 12556c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki if (DEBUG) { 12566c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki Slog.d(TAG, "Removing dangling bitmap file: " + child.getAbsolutePath()); 12576c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12586c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki child.delete(); 12596c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12606c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12616c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki } 12626c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki 12635504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @VisibleForTesting 12645504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki static class FileOutputStreamWithPath extends FileOutputStream { 12655504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki private final File mFile; 12665504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 12675504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki public FileOutputStreamWithPath(File file) throws FileNotFoundException { 12685504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki super(file); 12695504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki mFile = file; 12705504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 12715504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 12725504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki public File getFile() { 12735504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return mFile; 12745504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 12755504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 12765504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 12775504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki /** 12785504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki * Build the cached bitmap filename for a shortcut icon. 12795504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki * 12805504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki * The filename will be based on the ID, except certain characters will be escaped. 12815504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki */ 12825504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @VisibleForTesting 12835504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki FileOutputStreamWithPath openIconFileForWrite(@UserIdInt int userId, ShortcutInfo shortcut) 12845504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki throws IOException { 12855504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final File packagePath = new File(getUserBitmapFilePath(userId), 128622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki shortcut.getPackage()); 12875504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (!packagePath.isDirectory()) { 12885504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki packagePath.mkdirs(); 12895504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (!packagePath.isDirectory()) { 12905504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki throw new IOException("Unable to create directory " + packagePath); 12915504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 12925504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki SELinux.restorecon(packagePath); 12935504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 12945504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 12955504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final String baseName = String.valueOf(injectCurrentTimeMillis()); 1296b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki for (int suffix = 0; ; suffix++) { 12975504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final String filename = (suffix == 0 ? baseName : baseName + "_" + suffix) + ".png"; 12985504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final File file = new File(packagePath, filename); 12995504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (!file.exists()) { 13005504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (DEBUG) { 13015504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki Slog.d(TAG, "Saving icon to " + file.getAbsolutePath()); 13025504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13035504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return new FileOutputStreamWithPath(file); 13045504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13055504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13065504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13075504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 13085504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki void saveIconAndFixUpShortcut(@UserIdInt int userId, ShortcutInfo shortcut) { 13095504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (shortcut.hasIconFile() || shortcut.hasIconResource()) { 13105504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return; 13115504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13125504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 13134dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki final long token = injectClearCallingIdentity(); 13145504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki try { 13155504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // Clear icon info on the shortcut. 1316dd097812fa84b898a46cb5dd253422e78779a150Makoto Onuki removeIcon(userId, shortcut); 13175504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 13185504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final Icon icon = shortcut.getIcon(); 13195504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (icon == null) { 13205504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return; // has no icon 13215504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13225504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 1323abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Bitmap bitmap; 13245504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki try { 13255504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki switch (icon.getType()) { 13265504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki case Icon.TYPE_RESOURCE: { 13275504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki injectValidateIconResPackage(shortcut, icon); 13285504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 13295504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki shortcut.setIconResourceId(icon.getResId()); 13305504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_RES); 13315504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return; 13325504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13335504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki case Icon.TYPE_BITMAP: { 1334abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki bitmap = icon.getBitmap(); // Don't recycle in this case. 13355504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki break; 13365504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13375504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki default: 13385504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // This shouldn't happen because we've already validated the icon, but 13395504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // just in case. 13405504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki throw ShortcutInfo.getInvalidIconException(); 13415504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13425504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (bitmap == null) { 13435504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki Slog.e(TAG, "Null bitmap detected"); 13445504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return; 13455504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13465504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // Shrink and write to the file. 13475504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki File path = null; 13485504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki try { 13495504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final FileOutputStreamWithPath out = openIconFileForWrite(userId, shortcut); 13505504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki try { 13515504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki path = out.getFile(); 13525504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 1353abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Bitmap shrunk = shrinkBitmap(bitmap, mMaxIconDimension); 1354abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki try { 1355abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki shrunk.compress(mIconPersistFormat, mIconPersistQuality, out); 1356abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } finally { 1357abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki if (bitmap != shrunk) { 1358abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki shrunk.recycle(); 1359abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } 1360abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } 13615504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 13625504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki shortcut.setBitmapPath(out.getFile().getAbsolutePath()); 13635504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_FILE); 13645504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } finally { 13655504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki IoUtils.closeQuietly(out); 13665504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 1367b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } catch (IOException | RuntimeException e) { 13685504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // STOPSHIP Change wtf to e 13695504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki Slog.wtf(ShortcutService.TAG, "Unable to write bitmap to file", e); 13705504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (path != null && path.exists()) { 13715504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki path.delete(); 13725504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13735504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13745504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } finally { 13755504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // Once saved, we won't use the original icon information, so null it out. 13765504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki shortcut.clearIcon(); 13775504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13785504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } finally { 13794dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki injectRestoreCallingIdentity(token); 13805504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13815504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13825504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 13835504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // Unfortunately we can't do this check in unit tests because we fake creator package names, 13845504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // so override in unit tests. 13855504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // TODO CTS this case. 13865504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) { 138722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (!shortcut.getPackage().equals(icon.getResPackage())) { 13885504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki throw new IllegalArgumentException( 13895504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki "Icon resource must reside in shortcut owner package"); 13905504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13915504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 13925504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 13935504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @VisibleForTesting 13945504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki static Bitmap shrinkBitmap(Bitmap in, int maxSize) { 13955504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // Original width/height. 13965504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final int ow = in.getWidth(); 13975504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final int oh = in.getHeight(); 13985504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if ((ow <= maxSize) && (oh <= maxSize)) { 13995504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (DEBUG) { 14005504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki Slog.d(TAG, String.format("Icon size %dx%d, no need to shrink", ow, oh)); 14015504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 14025504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return in; 14035504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 14045504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final int longerDimension = Math.max(ow, oh); 14055504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 14065504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // New width and height. 14075504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final int nw = ow * maxSize / longerDimension; 14085504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final int nh = oh * maxSize / longerDimension; 14095504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (DEBUG) { 14105504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki Slog.d(TAG, String.format("Icon size %dx%d, shrinking to %dx%d", 14115504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki ow, oh, nw, nh)); 14125504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 14135504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 14145504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final Bitmap scaledBitmap = Bitmap.createBitmap(nw, nh, Bitmap.Config.ARGB_8888); 14155504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final Canvas c = new Canvas(scaledBitmap); 14165504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 14175504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final RectF dst = new RectF(0, 0, nw, nh); 14185504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 14195504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki c.drawBitmap(in, /*src=*/ null, dst, /* paint =*/ null); 14205504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 14215504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return scaledBitmap; 14225504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 14235504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 1424157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki /** 1425157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki * For a shortcut, update all resource names from resource IDs, and also update all 1426157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki * resource-based strings. 1427157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki */ 1428157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki void fixUpShortcutResourceNamesAndValues(ShortcutInfo si) { 1429157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki final Resources publisherRes = injectGetResourcesForApplicationAsUser( 1430157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki si.getPackage(), si.getUserId()); 1431157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki if (publisherRes != null) { 1432157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki final long start = injectElapsedRealtime(); 1433157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki try { 1434157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki si.lookupAndFillInResourceNames(publisherRes); 1435157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } finally { 1436157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki logDurationStat(Stats.RESOURCE_NAME_LOOKUP, start); 1437157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } 1438157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki si.resolveResourceStrings(publisherRes); 1439157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } 1440157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } 1441157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki 14425504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // === Caller validation === 14435504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 14446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private boolean isCallerSystem() { 14456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final int callingUid = injectBinderCallingUid(); 1446b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID); 14476f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 14486f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 14496f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private boolean isCallerShell() { 14506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final int callingUid = injectBinderCallingUid(); 14516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID; 14526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 14536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 14546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private void enforceSystemOrShell() { 14550b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki if (!(isCallerSystem() || isCallerShell())) { 14560b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki throw new SecurityException("Caller must be system or shell"); 14570b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki } 14586f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 14596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 14606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private void enforceShell() { 14610b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki if (!isCallerShell()) { 14620b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki throw new SecurityException("Caller must be shell"); 14630b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki } 14646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 14656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 14669da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki private void enforceSystem() { 14670b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki if (!isCallerSystem()) { 14680b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki throw new SecurityException("Caller must be system"); 14690b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki } 14709da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 14719da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 14724d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki private void enforceResetThrottlingPermission() { 14734d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki if (isCallerSystem()) { 14744d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki return; 14754d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 147676269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki enforceCallingOrSelfPermission( 14774d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki android.Manifest.permission.RESET_SHORTCUT_MANAGER_THROTTLING, null); 14784d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 14794d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 148076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki private void enforceCallingOrSelfPermission( 148176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki @NonNull String permission, @Nullable String message) { 148276269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki if (isCallerSystem()) { 148376269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki return; 148476269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 148576269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki injectEnforceCallingPermission(permission, message); 148676269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 148776269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 14884d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki /** 14894d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki * Somehow overriding ServiceContext.enforceCallingPermission() in the unit tests would confuse 14904d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki * mockito. So instead we extracted it here and override it in the tests. 14914d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki */ 14924d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @VisibleForTesting 14934d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki void injectEnforceCallingPermission( 14944d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @NonNull String permission, @Nullable String message) { 14954d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki mContext.enforceCallingPermission(permission, message); 14964d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 14974d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 14986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private void verifyCaller(@NonNull String packageName, @UserIdInt int userId) { 14996f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Preconditions.checkStringNotEmpty(packageName, "packageName"); 15006f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 15016f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (isCallerSystem()) { 15026f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return; // no check 15036f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15046f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 15056f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final int callingUid = injectBinderCallingUid(); 15066f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 15076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Otherwise, make sure the arguments are valid. 15086f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (UserHandle.getUserId(callingUid) != userId) { 15096f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki throw new SecurityException("Invalid user-ID"); 15106f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15115504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (injectGetPackageUid(packageName, userId) == injectBinderCallingUid()) { 15126f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return; // Caller is valid. 15136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15145ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki throw new SecurityException("Calling package name mismatch"); 15156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1517157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki // Overridden in unit tests to execute r synchronously. 1518157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki void injectPostToHandler(Runnable r) { 15194dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki mHandler.post(r); 15204dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 15214dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki 1522085a05cd864252314bcf5c339017a16b68105204Makoto Onuki void injectRunOnNewThread(Runnable r) { 1523085a05cd864252314bcf5c339017a16b68105204Makoto Onuki new Thread(r).start(); 1524085a05cd864252314bcf5c339017a16b68105204Makoto Onuki } 1525085a05cd864252314bcf5c339017a16b68105204Makoto Onuki 15266f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 15277001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki * @throws IllegalArgumentException if {@code numShortcuts} is bigger than 1528b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki * {@link #getMaxActivityShortcuts()}. 15296f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 15307001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki void enforceMaxActivityShortcuts(int numShortcuts) { 1531b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki if (numShortcuts > mMaxShortcuts) { 15326f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki throw new IllegalArgumentException("Max number of dynamic shortcuts exceeded"); 15336f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15346f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15356f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 15366f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 15377001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki * Return the max number of dynamic + manifest shortcuts for each launcher icon. 15387001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki */ 15397001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki int getMaxActivityShortcuts() { 1540b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki return mMaxShortcuts; 15417001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki } 15427001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 15437001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki /** 15446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * - Sends a notification to LauncherApps 15456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * - Write to file 15466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 154739686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki void packageShortcutsChanged(@NonNull String packageName, @UserIdInt int userId) { 154839686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki if (DEBUG) { 154939686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki Slog.d(TAG, String.format( 155039686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki "Shortcut changes: package=%s, user=%d", packageName, userId)); 155139686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki } 15526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki notifyListeners(packageName, userId); 15536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki scheduleSaveUser(userId); 15546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15556f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 15566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) { 1557157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki injectPostToHandler(() -> { 155802f338e23d06499790c6948709afb1587416eb40Makoto Onuki try { 155902f338e23d06499790c6948709afb1587416eb40Makoto Onuki final ArrayList<ShortcutChangeListener> copy; 156002f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 156102f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(userId)) { 156202f338e23d06499790c6948709afb1587416eb40Makoto Onuki return; 156302f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 156402f338e23d06499790c6948709afb1587416eb40Makoto Onuki 156502f338e23d06499790c6948709afb1587416eb40Makoto Onuki copy = new ArrayList<>(mListeners); 156602f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 156702f338e23d06499790c6948709afb1587416eb40Makoto Onuki // Note onShortcutChanged() needs to be called with the system service permissions. 156802f338e23d06499790c6948709afb1587416eb40Makoto Onuki for (int i = copy.size() - 1; i >= 0; i--) { 156902f338e23d06499790c6948709afb1587416eb40Makoto Onuki copy.get(i).onShortcutChanged(packageName, userId); 157002f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 157102f338e23d06499790c6948709afb1587416eb40Makoto Onuki } catch (Exception ignore) { 15724dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 15734dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki }); 15746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 15766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 15776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Clean up / validate an incoming shortcut. 15786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * - Make sure all mandatory fields are set. 15796f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * - Make sure the intent's extras are persistable, and them to set 15800eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki * {@link ShortcutInfo#mIntentPersistableExtrases}. Also clear its extras. 15816f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * - Clear flags. 15825504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki * 15835504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki * TODO Detailed unit tests 15846f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 15855504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) { 15866f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Preconditions.checkNotNull(shortcut, "Null shortcut detected"); 158722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (shortcut.getActivity() != null) { 15886f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Preconditions.checkState( 158922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki shortcut.getPackage().equals(shortcut.getActivity().getPackageName()), 1590b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki "Cannot publish shortcut: activity " + shortcut.getActivity() + " does not" 1591b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki + " belong to package " + shortcut.getPackage()); 159213260b6ff0438a02bd0f1c5bbcfb4fef71c82135Makoto Onuki Preconditions.checkState( 159313260b6ff0438a02bd0f1c5bbcfb4fef71c82135Makoto Onuki injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()), 159413260b6ff0438a02bd0f1c5bbcfb4fef71c82135Makoto Onuki "Cannot publish shortcut: activity " + shortcut.getActivity() + " is not" 159513260b6ff0438a02bd0f1c5bbcfb4fef71c82135Makoto Onuki + " main activity"); 15966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 15976f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 15985504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (!forUpdate) { 15995504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki shortcut.enforceMandatoryFields(); 1600b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki Preconditions.checkArgument( 1601b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()), 1602b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki "Cannot publish shortcut: " + shortcut.getActivity() + " is not main activity"); 16035504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 16045504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (shortcut.getIcon() != null) { 16055504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki ShortcutInfo.validateIcon(shortcut.getIcon()); 16065504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 16076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1608de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki shortcut.replaceFlags(0); 16095504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 16105504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 1611b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki /** 1612b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki * When a shortcut has no target activity, set the default one from the package. 1613b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki */ 1614b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki private void fillInDefaultActivity(List<ShortcutInfo> shortcuts) { 1615b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 1616b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki ComponentName defaultActivity = null; 1617b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki for (int i = shortcuts.size() - 1; i >= 0; i--) { 1618b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final ShortcutInfo si = shortcuts.get(i); 1619b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki if (si.getActivity() == null) { 1620b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki if (defaultActivity == null) { 1621b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki defaultActivity = injectGetDefaultMainActivity( 1622b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki si.getPackage(), si.getUserId()); 1623b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki Preconditions.checkState(defaultActivity != null, 1624b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki "Launcher activity not found for package " + si.getPackage()); 1625b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 1626b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki si.setActivity(defaultActivity); 1627b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 1628b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 1629b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 1630b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 16319e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki private void assignImplicitRanks(List<ShortcutInfo> shortcuts) { 16329e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki for (int i = shortcuts.size() - 1; i >= 0; i--) { 16339e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki shortcuts.get(i).setImplicitRank(i); 16349e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki } 16359e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki } 16369e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 16376f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // === APIs === 16386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 16396f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 16406f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public boolean setDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList, 16416f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @UserIdInt int userId) { 16426f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 16436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 16446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList(); 16456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final int size = newShortcuts.size(); 16466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 16476f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 164802f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 164902f338e23d06499790c6948709afb1587416eb40Makoto Onuki 1650c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 16516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 165222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.ensureImmutableShortcutsNotIncluded(newShortcuts); 165322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 1654b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki fillInDefaultActivity(newShortcuts); 1655b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 16567001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_SET); 16577001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 16586f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Throttling. 1659c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (!ps.tryApiCall()) { 16606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return false; 16616f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 16626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 16639e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // Initialize the implicit ranks for ShortcutPackage.adjustRanks(). 16649e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki ps.clearAllImplicitRanks(); 16659e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki assignImplicitRanks(newShortcuts); 16666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1667df6da040e00cba255cad64d2d231aae62928607aMakoto Onuki for (int i = 0; i < size; i++) { 1668df6da040e00cba255cad64d2d231aae62928607aMakoto Onuki fixUpIncomingShortcutInfo(newShortcuts.get(i), /* forUpdate= */ false); 1669df6da040e00cba255cad64d2d231aae62928607aMakoto Onuki } 1670df6da040e00cba255cad64d2d231aae62928607aMakoto Onuki 16716f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // First, remove all un-pinned; dynamic shortcuts 1672c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki ps.deleteAllDynamicShortcuts(); 16736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 16746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Then, add/update all. We need to make sure to take over "pinned" flag. 16756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki for (int i = 0; i < size; i++) { 16766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final ShortcutInfo newShortcut = newShortcuts.get(i); 167722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.addOrUpdateDynamicShortcut(newShortcut); 16786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 16799e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 16809e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // Lastly, adjust the ranks. 16819e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki ps.adjustRanks(); 16826f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 168339686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki packageShortcutsChanged(packageName, userId); 16847001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 16857001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStates(); 16867001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 16876f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return true; 16886f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 16896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 16906f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 16916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public boolean updateShortcuts(String packageName, ParceledListSlice shortcutInfoList, 16926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @UserIdInt int userId) { 16936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 16946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 16956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList(); 16965504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final int size = newShortcuts.size(); 16976f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 16986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 169902f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 170002f338e23d06499790c6948709afb1587416eb40Makoto Onuki 1701c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 17026f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 170322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.ensureImmutableShortcutsNotIncluded(newShortcuts); 170422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 1705b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki // For update, don't fill in the default activity. Having null activity means 1706b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki // "don't update the activity" here. 1707b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 17087001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_UPDATE); 17097001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 17105504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki // Throttling. 1711c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (!ps.tryApiCall()) { 17125504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return false; 17136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 17146f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 17159e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // Initialize the implicit ranks for ShortcutPackage.adjustRanks(). 17169e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki ps.clearAllImplicitRanks(); 17179e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki assignImplicitRanks(newShortcuts); 17189e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 17195504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki for (int i = 0; i < size; i++) { 17205504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final ShortcutInfo source = newShortcuts.get(i); 17215504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki fixUpIncomingShortcutInfo(source, /* forUpdate= */ true); 17225504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 17235504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final ShortcutInfo target = ps.findShortcutById(source.getId()); 17249e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki if (target == null) { 17259e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki continue; 17269e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki } 172722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 17289e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki if (target.isEnabled() != source.isEnabled()) { 17299e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki Slog.w(TAG, 17309e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki "ShortcutInfo.enabled cannot be changed with updateShortcuts()"); 17319e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki } 17325504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 17339e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // When updating the rank, we need to insert between existing ranks, so set 17349e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // this setRankChanged, and also copy the implicit rank fo adjustRanks(). 17359e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki if (source.hasRank()) { 17369e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki target.setRankChanged(); 17379e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki target.setImplicitRank(source.getImplicitRank()); 17389e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki } 173922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 17409e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki final boolean replacingIcon = (source.getIcon() != null); 17419e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki if (replacingIcon) { 17429e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki removeIcon(userId, target); 17439e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki } 17445504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 17459e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // Note copyNonNullFieldsFrom() does the "updatable with?" check too. 17469e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki target.copyNonNullFieldsFrom(source); 17479e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki target.setTimestamp(injectCurrentTimeMillis()); 17489e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 17499e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki if (replacingIcon) { 17509e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki saveIconAndFixUpShortcut(userId, target); 17519e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki } 17529e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 17539e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // When we're updating any resource related fields, re-extract the res names and 17549e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // the values. 17559e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki if (replacingIcon || source.hasStringResources()) { 17569e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki fixUpShortcutResourceNamesAndValues(target); 17575504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 17585504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 17599e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 17609e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // Lastly, adjust the ranks. 17619e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki ps.adjustRanks(); 17626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 176339686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki packageShortcutsChanged(packageName, userId); 17646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 17657001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStates(); 17667001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 17676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return true; 17686f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 17696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 17706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 1771b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki public boolean addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList, 17726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @UserIdInt int userId) { 17736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 17746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1775b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList(); 1776b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki final int size = newShortcuts.size(); 1777b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki 17786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 177902f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 178002f338e23d06499790c6948709afb1587416eb40Makoto Onuki 1781c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 17826f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 178322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.ensureImmutableShortcutsNotIncluded(newShortcuts); 178422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 1785b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki fillInDefaultActivity(newShortcuts); 1786b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 17877001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_ADD); 17887001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 17899e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // Initialize the implicit ranks for ShortcutPackage.adjustRanks(). 17909e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki ps.clearAllImplicitRanks(); 17919e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki assignImplicitRanks(newShortcuts); 17929e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 17936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Throttling. 1794c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (!ps.tryApiCall()) { 17956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return false; 17966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 1797b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki for (int i = 0; i < size; i++) { 1798b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki final ShortcutInfo newShortcut = newShortcuts.get(i); 17996f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1800b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki // Validate the shortcut. 1801b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false); 18026f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 18039e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // When ranks are changing, we need to insert between ranks, so set the 18049e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // "rank changed" flag. 18059e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki newShortcut.setRankChanged(); 18069e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 1807b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki // Add it. 180822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.addOrUpdateDynamicShortcut(newShortcut); 1809b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki } 18109e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 18119e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // Lastly, adjust the ranks. 18129e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki ps.adjustRanks(); 18136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 181439686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki packageShortcutsChanged(packageName, userId); 18156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 18167001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStates(); 18177001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 18186f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return true; 18196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 18206f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 18216f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 182220c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki public void disableShortcuts(String packageName, List shortcutIds, 1823d6880797f72e1e397e18c6e709c0125f795c7d2eMakoto Onuki CharSequence disabledMessage, int disabledMessageResId, @UserIdInt int userId) { 182420c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki verifyCaller(packageName, userId); 182520c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided"); 182620c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki 182720c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki synchronized (mLock) { 182802f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 182902f338e23d06499790c6948709afb1587416eb40Makoto Onuki 1830c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 183122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 183222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds); 183322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 1834d6880797f72e1e397e18c6e709c0125f795c7d2eMakoto Onuki final String disabledMessageString = 1835d6880797f72e1e397e18c6e709c0125f795c7d2eMakoto Onuki (disabledMessage == null) ? null : disabledMessage.toString(); 1836d6880797f72e1e397e18c6e709c0125f795c7d2eMakoto Onuki 183722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki for (int i = shortcutIds.size() - 1; i >= 0; i--) { 183822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.disableWithId(Preconditions.checkStringNotEmpty((String) shortcutIds.get(i)), 1839d6880797f72e1e397e18c6e709c0125f795c7d2eMakoto Onuki disabledMessageString, disabledMessageResId, 184022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki /* overrideImmutable=*/ false); 184122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 18429e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 18439e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks. 18449e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki ps.adjustRanks(); 184522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 184622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki packageShortcutsChanged(packageName, userId); 18477001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 18487001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStates(); 184922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 185022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 185122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @Override 185222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki public void enableShortcuts(String packageName, List shortcutIds, @UserIdInt int userId) { 185322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki verifyCaller(packageName, userId); 185422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided"); 185522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 185622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki synchronized (mLock) { 185702f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 185802f338e23d06499790c6948709afb1587416eb40Makoto Onuki 1859c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 186022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 186122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds); 186222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 186322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki for (int i = shortcutIds.size() - 1; i >= 0; i--) { 186422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.enableWithId((String) shortcutIds.get(i)); 186522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 186620c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki } 186720c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki packageShortcutsChanged(packageName, userId); 18687001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 18697001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStates(); 187020c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki } 187120c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki 187220c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki @Override 1873b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki public void removeDynamicShortcuts(String packageName, List shortcutIds, 18746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @UserIdInt int userId) { 18756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 1876b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided"); 18776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 18786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 187902f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 188002f338e23d06499790c6948709afb1587416eb40Makoto Onuki 1881c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 188222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 188322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds); 188422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 1885b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki for (int i = shortcutIds.size() - 1; i >= 0; i--) { 188622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ps.deleteDynamicWithId( 1887b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki Preconditions.checkStringNotEmpty((String) shortcutIds.get(i))); 1888b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki } 18899e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 18909e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki // We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks. 18919e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki ps.adjustRanks(); 18926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 189339686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki packageShortcutsChanged(packageName, userId); 18947001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 18957001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStates(); 18966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 18976f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 18986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 1899b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki public void removeAllDynamicShortcuts(String packageName, @UserIdInt int userId) { 19006f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 19016f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19026f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 190302f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 190402f338e23d06499790c6948709afb1587416eb40Makoto Onuki 1905c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 19064e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki ps.deleteAllDynamicShortcuts(); 19076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 190839686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki packageShortcutsChanged(packageName, userId); 19097001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 19107001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStates(); 19116f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19126f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 19146f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public ParceledListSlice<ShortcutInfo> getDynamicShortcuts(String packageName, 19156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @UserIdInt int userId) { 19166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 19179c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki 19186f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 191902f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 192002f338e23d06499790c6948709afb1587416eb40Makoto Onuki 19216f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return getShortcutsWithQueryLocked( 19226f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR, 19236f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki ShortcutInfo::isDynamic); 19246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19256f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19266f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19276f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 192822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki public ParceledListSlice<ShortcutInfo> getManifestShortcuts(String packageName, 192922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @UserIdInt int userId) { 193022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki verifyCaller(packageName, userId); 19319c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki 193222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki synchronized (mLock) { 193302f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 193402f338e23d06499790c6948709afb1587416eb40Makoto Onuki 193522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return getShortcutsWithQueryLocked( 193622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR, 193722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ShortcutInfo::isManifestShortcut); 193822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 193922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 194022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 194122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @Override 19426f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public ParceledListSlice<ShortcutInfo> getPinnedShortcuts(String packageName, 19436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @UserIdInt int userId) { 19446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 19459c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki 19466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 194702f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 194802f338e23d06499790c6948709afb1587416eb40Makoto Onuki 19496f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return getShortcutsWithQueryLocked( 19506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR, 19516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki ShortcutInfo::isPinned); 19526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19556f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName, 19566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> query) { 19576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19586f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final ArrayList<ShortcutInfo> ret = new ArrayList<>(); 19596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1960c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 19614e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki ps.findAll(ret, query, cloneFlags); 19626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19636f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return new ParceledListSlice<>(ret); 19646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 1967d6880797f72e1e397e18c6e709c0125f795c7d2eMakoto Onuki public int getMaxShortcutCountPerActivity(String packageName, @UserIdInt int userId) 19686f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki throws RemoteException { 19696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 19706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 1971b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki return mMaxShortcuts; 19726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 19756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public int getRemainingCallCount(String packageName, @UserIdInt int userId) { 19766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 19776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 197902f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 198002f338e23d06499790c6948709afb1587416eb40Makoto Onuki 1981c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 19824e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki return mMaxUpdatesPerInterval - ps.getApiCallCount(); 19836f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19846f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19856f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19866f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 19876f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public long getRateLimitResetTime(String packageName, @UserIdInt int userId) { 19886f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki verifyCaller(packageName, userId); 19896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19906f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 199102f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 199202f338e23d06499790c6948709afb1587416eb40Makoto Onuki 19936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return getNextResetTimeLocked(); 19946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 19966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 19975504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @Override 199820c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki public int getIconMaxDimensions(String packageName, int userId) { 19995ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki verifyCaller(packageName, userId); 20005ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 20015504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki synchronized (mLock) { 20025504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return mMaxIconDimension; 20035504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 20045504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 20055504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 200620c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki @Override 200720c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki public void reportShortcutUsed(String packageName, String shortcutId, int userId) { 200820c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki verifyCaller(packageName, userId); 200920c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki 2010ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki Preconditions.checkNotNull(shortcutId); 2011ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki 2012ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki if (DEBUG) { 2013ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki Slog.d(TAG, String.format("reportShortcutUsed: Shortcut %s package %s used on user %d", 2014ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki shortcutId, packageName, userId)); 2015ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki } 2016ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki 2017ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki synchronized (mLock) { 201802f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 201902f338e23d06499790c6948709afb1587416eb40Makoto Onuki 2020c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); 20214e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki 2022ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki if (ps.findShortcutById(shortcutId) == null) { 2023ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki Log.w(TAG, String.format("reportShortcutUsed: package %s doesn't have shortcut %s", 2024ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki packageName, shortcutId)); 2025ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki return; 2026ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki } 2027ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki } 2028ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki 2029ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki final long token = injectClearCallingIdentity(); 2030ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki try { 2031ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki mUsageStatsManagerInternal.reportShortcutUsage(packageName, shortcutId, userId); 2032ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki } finally { 2033ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki injectRestoreCallingIdentity(token); 2034ac042501c816fa9a65aed005060ebdcfc0a0f3b2Makoto Onuki } 203520c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki } 203620c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki 20376f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 2038b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki * Reset all throttling, for developer options and command line. Only system/shell can call 2039b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki * it. 20406f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 20416f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 20426f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void resetThrottling() { 20436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki enforceSystemOrShell(); 20446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 20454554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki resetThrottlingInner(getCallingUserId()); 20466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 20476f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 20484554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki void resetThrottlingInner(@UserIdInt int userId) { 20496f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 205002f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(userId)) { 205102f338e23d06499790c6948709afb1587416eb40Makoto Onuki Log.w(TAG, "User " + userId + " is locked or not running"); 205202f338e23d06499790c6948709afb1587416eb40Makoto Onuki return; 205302f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 205402f338e23d06499790c6948709afb1587416eb40Makoto Onuki 20554554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki getUserShortcutsLocked(userId).resetThrottling(); 20566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 20574554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki scheduleSaveUser(userId); 20585ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki Slog.i(TAG, "ShortcutManager: throttling counter reset for user " + userId); 20595ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki } 20605ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 20615ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki void resetAllThrottlingInner() { 20625ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki synchronized (mLock) { 20635ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki mRawLastResetTime = injectCurrentTimeMillis(); 20645ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki } 20655ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki scheduleSaveBaseState(); 20665ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki Slog.i(TAG, "ShortcutManager: throttling counter reset for all users"); 20676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 20686f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 20694d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @Override 20704d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki public void onApplicationActive(String packageName, int userId) { 20714d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki if (DEBUG) { 20724d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki Slog.d(TAG, "onApplicationActive: package=" + packageName + " userid=" + userId); 20734d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 20744d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki enforceResetThrottlingPermission(); 207502f338e23d06499790c6948709afb1587416eb40Makoto Onuki 207602f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 207702f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(userId)) { 207802f338e23d06499790c6948709afb1587416eb40Makoto Onuki // This is called by system UI, so no need to throw. Just ignore. 207902f338e23d06499790c6948709afb1587416eb40Makoto Onuki return; 208002f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 208102f338e23d06499790c6948709afb1587416eb40Makoto Onuki 208202f338e23d06499790c6948709afb1587416eb40Makoto Onuki getPackageShortcutsLocked(packageName, userId) 208302f338e23d06499790c6948709afb1587416eb40Makoto Onuki .resetRateLimitingForCommandLineNoSaving(); 208402f338e23d06499790c6948709afb1587416eb40Makoto Onuki saveUserLocked(userId); 20859c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki } 20864d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 20874d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 20882d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // We override this method in unit tests to do a simpler check. 20892d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) { 20901030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki final long start = injectElapsedRealtime(); 20911030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki try { 20921030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki return hasShortcutHostPermissionInner(callingPackage, userId); 20931030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki } finally { 20941030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki logDurationStat(Stats.LAUNCHER_PERMISSION_CHECK, start); 20951030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki } 20962d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 20972d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 20982d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // This method is extracted so we can directly call this method from unit tests, 20992d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // even when hasShortcutPermission() is overridden. 21002d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki @VisibleForTesting 21012d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki boolean hasShortcutHostPermissionInner(@NonNull String callingPackage, int userId) { 21022d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki synchronized (mLock) { 210302f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 210402f338e23d06499790c6948709afb1587416eb40Makoto Onuki 21053145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final ShortcutUser user = getUserShortcutsLocked(userId); 21062d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 21071030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki // Always trust the in-memory cache. 21081030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki final ComponentName cached = user.getCachedLauncher(); 21091030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki if (cached != null) { 21101030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki if (cached.getPackageName().equals(callingPackage)) { 21111030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki return true; 21121030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki } 21131030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki } 21141030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki // If the cached one doesn't match, then go ahead 21151030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki 21162d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki final List<ResolveInfo> allHomeCandidates = new ArrayList<>(); 21172d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 21182d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // Default launcher from package manager. 21196c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final long startGetHomeActivitiesAsUser = injectElapsedRealtime(); 21201030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki final ComponentName defaultLauncher = mPackageManagerInternal 21212d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki .getHomeActivitiesAsUser(allHomeCandidates, userId); 21222e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki logDurationStat(Stats.GET_DEFAULT_HOME, startGetHomeActivitiesAsUser); 21232d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 21242d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki ComponentName detected; 21252d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (defaultLauncher != null) { 21262d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki detected = defaultLauncher; 21272d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (DEBUG) { 21282d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki Slog.v(TAG, "Default launcher from PM: " + detected); 21292d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21302d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } else { 21311030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki detected = user.getLastKnownLauncher(); 21322d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 2133ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (detected != null) { 2134ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (injectIsActivityEnabledAndExported(detected, userId)) { 2135ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (DEBUG) { 2136ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki Slog.v(TAG, "Cached launcher: " + detected); 2137ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2138ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } else { 2139ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki Slog.w(TAG, "Cached launcher " + detected + " no longer exists"); 2140ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki detected = null; 21411030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki user.clearLauncher(); 2142ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 21432d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21442d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21452d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 21462d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (detected == null) { 21472d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // If we reach here, that means it's the first check since the user was created, 21482d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // and there's already multiple launchers and there's no default set. 21492d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // Find the system one with the highest priority. 21502d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // (We need to check the priority too because of FallbackHome in Settings.) 21512d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // If there's no system launcher yet, then no one can access shortcuts, until 21522d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // the user explicitly 21532d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki final int size = allHomeCandidates.size(); 21542d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 21552d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki int lastPriority = Integer.MIN_VALUE; 21562d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki for (int i = 0; i < size; i++) { 21572d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki final ResolveInfo ri = allHomeCandidates.get(i); 21582d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (!ri.activityInfo.applicationInfo.isSystemApp()) { 21592d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki continue; 21602d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21612d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (DEBUG) { 21622d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki Slog.d(TAG, String.format("hasShortcutPermissionInner: pkg=%s prio=%d", 21632d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki ri.activityInfo.getComponentName(), ri.priority)); 21642d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21652d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (ri.priority < lastPriority) { 21662d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki continue; 21672d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21682d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki detected = ri.activityInfo.getComponentName(); 21692d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki lastPriority = ri.priority; 21702d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21712d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21722e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 21731030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki // Update the cache. 21741030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki user.setLauncher(detected); 21752d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (detected != null) { 21762d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (DEBUG) { 21772d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki Slog.v(TAG, "Detected launcher: " + detected); 21782d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21792d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki return detected.getPackageName().equals(callingPackage); 21802d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } else { 21812d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // Default launcher not found. 21822d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki return false; 21832d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21842d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21852d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 21862d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 2187cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki // === House keeping === 2188cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 2189b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki private void cleanUpPackageForAllLoadedUsers(String packageName, @UserIdInt int packageUserId, 2190b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki boolean appStillExists) { 21919ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki synchronized (mLock) { 21929ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki forEachLoadedUserLocked(user -> 2193b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki cleanUpPackageLocked(packageName, user.getUserId(), packageUserId, 2194b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki appStillExists)); 21959ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki } 21965ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki } 21975ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 21982e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki /** 21992e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki * Remove all the information associated with a package. This will really remove all the 22002e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki * information, including the restore information (i.e. it'll remove packages even if they're 22012e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki * shadow). 22029ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki * 22039ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki * This is called when an app is uninstalled, or an app gets "clear data"ed. 22042e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki */ 22059ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki @VisibleForTesting 2206b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId, 2207b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki boolean appStillExists) { 2208d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki final boolean wasUserLoaded = isUserLoadedLocked(owningUserId); 2209cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 22109ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki final ShortcutUser user = getUserShortcutsLocked(owningUserId); 2211cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki boolean doNotify = false; 2212cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 2213cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki // First, remove the package from the package list (if the package is a publisher). 2214d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki if (packageUserId == owningUserId) { 2215c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (user.removePackage(packageName) != null) { 2216d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki doNotify = true; 2217d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 2218cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2219d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 2220cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki // Also remove from the launcher list (if the package is a launcher). 22219ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki user.removeLauncher(packageUserId, packageName); 2222cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 2223cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki // Then remove pinned shortcuts from all launchers. 22244d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki user.forAllLaunchers(l -> l.cleanUpPackage(packageName, packageUserId)); 22254d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 22264d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki // Now there may be orphan shortcuts because we removed pinned shortcuts at the previous 2227cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki // step. Remove them too. 2228c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki user.forAllPackages(p -> p.refreshPinnedFlags()); 2229cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 2230d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki scheduleSaveUser(owningUserId); 2231cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 2232cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki if (doNotify) { 2233d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki notifyListeners(packageName, owningUserId); 2234cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2235cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 2236b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki // If the app still exists (i.e. data cleared), we need to re-publish manifest shortcuts. 2237b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki if (appStillExists && (packageUserId == owningUserId)) { 2238b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki // This will do the notification and save when needed, so do it after the above 2239b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki // notifyListeners. 22404e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ true); 2241b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 2242b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 2243cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki if (!wasUserLoaded) { 2244cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki // Note this will execute the scheduled save. 2245d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki unloadUserLocked(owningUserId); 2246cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2247cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2248cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 22496f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 22506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Entry point from {@link LauncherApps}. 22516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 22526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private class LocalService extends ShortcutServiceInternal { 22532e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 22546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 2255d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki public List<ShortcutInfo> getShortcuts(int launcherUserId, 22566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @NonNull String callingPackage, long changedSince, 2257abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki @Nullable String packageName, @Nullable List<String> shortcutIds, 2258abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki @Nullable ComponentName componentName, 22596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki int queryFlags, int userId) { 22606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final ArrayList<ShortcutInfo> ret = new ArrayList<>(); 22619c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki 226220c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki final boolean cloneKeyFieldOnly = 226320c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki ((queryFlags & ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY) != 0); 226420c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki final int cloneFlag = cloneKeyFieldOnly ? ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO 226520c95f854e54b71caa49f0efe07d47d1e6afd435Makoto Onuki : ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER; 2266abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki if (packageName == null) { 2267abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki shortcutIds = null; // LauncherAppsService already threw for it though. 2268abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } 22696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 22706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 227102f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 227202f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(launcherUserId); 227302f338e23d06499790c6948709afb1587416eb40Makoto Onuki 22742e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki getLauncherShortcutsLocked(callingPackage, userId, launcherUserId) 2275c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .attemptToRestoreIfNeededAndSave(); 22762e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 22776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (packageName != null) { 2278d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki getShortcutsInnerLocked(launcherUserId, 2279abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki callingPackage, packageName, shortcutIds, changedSince, 2280de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki componentName, queryFlags, userId, ret, cloneFlag); 22816f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } else { 22824d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki final List<String> shortcutIdsF = shortcutIds; 22834d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki getUserShortcutsLocked(userId).forAllPackages(p -> { 2284d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki getShortcutsInnerLocked(launcherUserId, 22854d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki callingPackage, p.getPackageName(), shortcutIdsF, changedSince, 2286de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki componentName, queryFlags, userId, ret, cloneFlag); 22874d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki }); 22886f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 22896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 22906f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return ret; 22916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 22926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2293d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage, 2294abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki @Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince, 22956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Nullable ComponentName componentName, int queryFlags, 22966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) { 2297abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki final ArraySet<String> ids = shortcutIds == null ? null 2298abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki : new ArraySet<>(shortcutIds); 2299abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki 2300c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki final ShortcutPackage p = getUserShortcutsLocked(userId) 2301c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .getPackageShortcutsIfExists(packageName); 2302c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (p == null) { 2303c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki return; // No need to instantiate ShortcutPackage. 2304c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki } 2305c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki 2306c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki p.findAll(ret, 23076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki (ShortcutInfo si) -> { 23086f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (si.getLastChangedTimestamp() < changedSince) { 23096f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return false; 23106f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 2311abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki if (ids != null && !ids.contains(si.getId())) { 2312abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki return false; 2313abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } 231485694526039fb0a80ab74b2dc3ab17bacc1a4a59Makoto Onuki if (componentName != null) { 231522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (si.getActivity() != null 231622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki && !si.getActivity().equals(componentName)) { 231785694526039fb0a80ab74b2dc3ab17bacc1a4a59Makoto Onuki return false; 231885694526039fb0a80ab74b2dc3ab17bacc1a4a59Makoto Onuki } 23196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 232022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0) 232122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki && si.isDynamic()) { 232222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return true; 232322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 232422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0) 232522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki && si.isPinned()) { 232622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return true; 232722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 232822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (((queryFlags & ShortcutQuery.FLAG_GET_MANIFEST) != 0) 232922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki && si.isManifestShortcut()) { 233022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return true; 233122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 233222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return false; 2333d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki }, cloneFlag, callingPackage, launcherUserId); 23346f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 23356f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 23366f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 2337d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki public boolean isPinnedByCaller(int launcherUserId, @NonNull String callingPackage, 2338d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki @NonNull String packageName, @NonNull String shortcutId, int userId) { 2339d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki Preconditions.checkStringNotEmpty(packageName, "packageName"); 2340d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki Preconditions.checkStringNotEmpty(shortcutId, "shortcutId"); 2341d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 2342d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki synchronized (mLock) { 234302f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 234402f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(launcherUserId); 234502f338e23d06499790c6948709afb1587416eb40Makoto Onuki 23462e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki getLauncherShortcutsLocked(callingPackage, userId, launcherUserId) 2347c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .attemptToRestoreIfNeededAndSave(); 23482e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 2349d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki final ShortcutInfo si = getShortcutInfoLocked( 2350d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki launcherUserId, callingPackage, packageName, shortcutId, userId); 2351d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return si != null && si.isPinned(); 2352d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 2353d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 2354d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 23552e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki private ShortcutInfo getShortcutInfoLocked( 2356d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki int launcherUserId, @NonNull String callingPackage, 2357d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki @NonNull String packageName, @NonNull String shortcutId, int userId) { 2358d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki Preconditions.checkStringNotEmpty(packageName, "packageName"); 2359d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki Preconditions.checkStringNotEmpty(shortcutId, "shortcutId"); 2360d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 236102f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 236202f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(launcherUserId); 23639c850012cacf0af4a392294566a8c7c897dc8771Makoto Onuki 2364c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki final ShortcutPackage p = getUserShortcutsLocked(userId) 2365c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .getPackageShortcutsIfExists(packageName); 2366c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (p == null) { 2367c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki return null; 2368c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki } 2369c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki 2370d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki final ArrayList<ShortcutInfo> list = new ArrayList<>(1); 2371c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki p.findAll(list, 2372d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki (ShortcutInfo si) -> shortcutId.equals(si.getId()), 2373d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki /* clone flags=*/ 0, callingPackage, launcherUserId); 2374d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return list.size() == 0 ? null : list.get(0); 2375d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 2376d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 2377d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki @Override 2378d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki public void pinShortcuts(int launcherUserId, 2379d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki @NonNull String callingPackage, @NonNull String packageName, 23806f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @NonNull List<String> shortcutIds, int userId) { 23816f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Calling permission must be checked by LauncherAppsImpl. 23826f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Preconditions.checkStringNotEmpty(packageName, "packageName"); 23836f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Preconditions.checkNotNull(shortcutIds, "shortcutIds"); 23846f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 23856f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 238602f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 238702f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(launcherUserId); 238802f338e23d06499790c6948709afb1587416eb40Makoto Onuki 23899da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final ShortcutLauncher launcher = 23902e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki getLauncherShortcutsLocked(callingPackage, userId, launcherUserId); 2391c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki launcher.attemptToRestoreIfNeededAndSave(); 23929da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 2393c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki launcher.pinShortcuts(userId, packageName, shortcutIds); 23946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 239539686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki packageShortcutsChanged(packageName, userId); 23967001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 23977001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStates(); 23986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 23996f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 24006f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 2401440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki public Intent[] createShortcutIntents(int launcherUserId, 2402d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki @NonNull String callingPackage, 240343204b8357d781f284037fb8b7b7050ed04a2103Makoto Onuki @NonNull String packageName, @NonNull String shortcutId, int userId) { 24046f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Calling permission must be checked by LauncherAppsImpl. 240543204b8357d781f284037fb8b7b7050ed04a2103Makoto Onuki Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty"); 240643204b8357d781f284037fb8b7b7050ed04a2103Makoto Onuki Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty"); 24076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 24086f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 240902f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 241002f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(launcherUserId); 241102f338e23d06499790c6948709afb1587416eb40Makoto Onuki 24122e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki getLauncherShortcutsLocked(callingPackage, userId, launcherUserId) 2413c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .attemptToRestoreIfNeededAndSave(); 24142e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 2415d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki // Make sure the shortcut is actually visible to the launcher. 2416d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki final ShortcutInfo si = getShortcutInfoLocked( 2417d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki launcherUserId, callingPackage, packageName, shortcutId, userId); 2418d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki // "si == null" should suffice here, but check the flags too just to make sure. 241922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (si == null || !si.isEnabled() || !si.isAlive()) { 242083f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki Log.e(TAG, "Shortcut " + shortcutId + " does not exist or disabled"); 2421d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return null; 2422d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 2423440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki return si.getIntents(); 24246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 24256f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 24266f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 24276f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 24286f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void addListener(@NonNull ShortcutChangeListener listener) { 24296f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 24306f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mListeners.add(Preconditions.checkNotNull(listener)); 24316f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 24326f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 24335504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 24345504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @Override 2435abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki public int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage, 2436abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki @NonNull String packageName, @NonNull String shortcutId, int userId) { 2437abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Preconditions.checkNotNull(callingPackage, "callingPackage"); 2438abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Preconditions.checkNotNull(packageName, "packageName"); 2439abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Preconditions.checkNotNull(shortcutId, "shortcutId"); 24405504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 24415504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki synchronized (mLock) { 244202f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 244302f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(launcherUserId); 244402f338e23d06499790c6948709afb1587416eb40Makoto Onuki 24452e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki getLauncherShortcutsLocked(callingPackage, userId, launcherUserId) 2446c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .attemptToRestoreIfNeededAndSave(); 24472e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 2448c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki final ShortcutPackage p = getUserShortcutsLocked(userId) 2449c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .getPackageShortcutsIfExists(packageName); 2450c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (p == null) { 2451c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki return 0; 2452c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki } 2453c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki 2454c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki final ShortcutInfo shortcutInfo = p.findShortcutById(shortcutId); 24555504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return (shortcutInfo != null && shortcutInfo.hasIconResource()) 24565504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki ? shortcutInfo.getIconResourceId() : 0; 24575504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 24585504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 24595504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 24605504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @Override 2461d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki public ParcelFileDescriptor getShortcutIconFd(int launcherUserId, 2462abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki @NonNull String callingPackage, @NonNull String packageName, 2463abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki @NonNull String shortcutId, int userId) { 2464abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Preconditions.checkNotNull(callingPackage, "callingPackage"); 2465abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Preconditions.checkNotNull(packageName, "packageName"); 2466abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Preconditions.checkNotNull(shortcutId, "shortcutId"); 24675504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 24685504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki synchronized (mLock) { 246902f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(userId); 247002f338e23d06499790c6948709afb1587416eb40Makoto Onuki throwIfUserLockedL(launcherUserId); 247102f338e23d06499790c6948709afb1587416eb40Makoto Onuki 24722e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki getLauncherShortcutsLocked(callingPackage, userId, launcherUserId) 2473c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .attemptToRestoreIfNeededAndSave(); 2474c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki 2475c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki final ShortcutPackage p = getUserShortcutsLocked(userId) 2476c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki .getPackageShortcutsIfExists(packageName); 2477c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki if (p == null) { 2478c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki return null; 2479c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki } 24802e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 2481c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki final ShortcutInfo shortcutInfo = p.findShortcutById(shortcutId); 24825504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki if (shortcutInfo == null || !shortcutInfo.hasIconFile()) { 24835504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return null; 24845504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 24855504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki try { 248634d1c919fd4f6b9f1adb7d62dd16ba1fa8e91c79Makoto Onuki if (shortcutInfo.getBitmapPath() == null) { 248734d1c919fd4f6b9f1adb7d62dd16ba1fa8e91c79Makoto Onuki Slog.w(TAG, "null bitmap detected in getShortcutIconFd()"); 248834d1c919fd4f6b9f1adb7d62dd16ba1fa8e91c79Makoto Onuki return null; 248934d1c919fd4f6b9f1adb7d62dd16ba1fa8e91c79Makoto Onuki } 24905504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return ParcelFileDescriptor.open( 24915504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki new File(shortcutInfo.getBitmapPath()), 24925504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki ParcelFileDescriptor.MODE_READ_ONLY); 24935504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } catch (FileNotFoundException e) { 24945504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki Slog.e(TAG, "Icon file not found: " + shortcutInfo.getBitmapPath()); 24955504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return null; 24965504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 24975504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 24985504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 24992d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 25002d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki @Override 2501d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki public boolean hasShortcutHostPermission(int launcherUserId, 2502d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki @NonNull String callingPackage) { 2503d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return ShortcutService.this.hasShortcutHostPermission(callingPackage, launcherUserId); 25042d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 25054e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 25064d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 25074e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final BroadcastReceiver mReceiver = new BroadcastReceiver() { 25084d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @Override 25094e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki public void onReceive(Context context, Intent intent) { 25104e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki if (!mBootCompleted.get()) { 25114e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki return; // Boot not completed, ignore the broadcast. 25124e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 251302f338e23d06499790c6948709afb1587416eb40Makoto Onuki try { 251402f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) { 251502f338e23d06499790c6948709afb1587416eb40Makoto Onuki handleLocaleChanged(); 251602f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 251702f338e23d06499790c6948709afb1587416eb40Makoto Onuki } catch (Exception e) { 251802f338e23d06499790c6948709afb1587416eb40Makoto Onuki wtf("Exception in mReceiver.onReceive", e); 2519a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki } 2520a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki } 25214e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki }; 25226f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 2523157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki void handleLocaleChanged() { 2524157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki if (DEBUG) { 2525157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki Slog.d(TAG, "handleLocaleChanged"); 2526157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } 2527157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki scheduleSaveBaseState(); 2528157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki 252902f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 253002f338e23d06499790c6948709afb1587416eb40Makoto Onuki final long token = injectClearCallingIdentity(); 253102f338e23d06499790c6948709afb1587416eb40Makoto Onuki try { 253202f338e23d06499790c6948709afb1587416eb40Makoto Onuki forEachLoadedUserLocked(user -> user.detectLocaleChange()); 253302f338e23d06499790c6948709afb1587416eb40Makoto Onuki } finally { 253402f338e23d06499790c6948709afb1587416eb40Makoto Onuki injectRestoreCallingIdentity(token); 253502f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 2536157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } 2537157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } 2538157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki 2539f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki /** 2540f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki * Package event callbacks. 2541f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki */ 2542f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki @VisibleForTesting 25434e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final BroadcastReceiver mPackageMonitor = new BroadcastReceiver() { 2544f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki @Override 2545f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki public void onReceive(Context context, Intent intent) { 25464e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); 25474e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki if (userId == UserHandle.USER_NULL) { 25484e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki Slog.w(TAG, "Intent broadcast does not contain user handle: " + intent); 25494e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki return; 25504e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 25514e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki 25524e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final String action = intent.getAction(); 25534e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki 25544e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki // This is normally called on Handler, so clearCallingIdentity() isn't needed, 25554e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki // but we still check it in unit tests. 2556f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki final long token = injectClearCallingIdentity(); 2557f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki try { 255802f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 255902f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(userId)) { 256002f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (DEBUG) { 256102f338e23d06499790c6948709afb1587416eb40Makoto Onuki Slog.d(TAG, "Ignoring package broadcast " + action 256202f338e23d06499790c6948709afb1587416eb40Makoto Onuki + " for locked/stopped user " + userId); 256302f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 256402f338e23d06499790c6948709afb1587416eb40Makoto Onuki return; 25654e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 2566b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 256702f338e23d06499790c6948709afb1587416eb40Makoto Onuki // Whenever we get one of those package broadcasts, or get 256802f338e23d06499790c6948709afb1587416eb40Makoto Onuki // ACTION_PREFERRED_ACTIVITY_CHANGED, we purge the default launcher cache. 25691030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki final ShortcutUser user = getUserShortcutsLocked(userId); 25701030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki user.clearLauncher(); 25711030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki } 25721030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki if (Intent.ACTION_PREFERRED_ACTIVITY_CHANGED.equals(action)) { 25731030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki // Nothing farther to do. 25741030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki return; 25751030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki } 25761030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki 25774e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final Uri intentUri = intent.getData(); 25784e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final String packageName = (intentUri != null) ? intentUri.getSchemeSpecificPart() 25794e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki : null; 25804e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki if (packageName == null) { 25814e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki Slog.w(TAG, "Intent broadcast does not contain package name: " + intent); 25824e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki return; 25834e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 2584a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki 25854e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); 2586efbbe7ea9db8adab6bff407db1d7fc54bbaf31eeMakoto Onuki 25874e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki switch (action) { 25884e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki case Intent.ACTION_PACKAGE_ADDED: 25894e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki if (replacing) { 25904e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki handlePackageUpdateFinished(packageName, userId); 25914e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } else { 25924e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki handlePackageAdded(packageName, userId); 25934e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 25944e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki break; 25954e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki case Intent.ACTION_PACKAGE_REMOVED: 25964e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki if (!replacing) { 25974e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki handlePackageRemoved(packageName, userId); 25984e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 25994e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki break; 26004e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki case Intent.ACTION_PACKAGE_CHANGED: 26014e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki handlePackageChanged(packageName, userId); 2602f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki 26034e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki break; 26044e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki case Intent.ACTION_PACKAGE_DATA_CLEARED: 26054e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki handlePackageDataCleared(packageName, userId); 26064e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki break; 26074e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 260802f338e23d06499790c6948709afb1587416eb40Makoto Onuki } catch (Exception e) { 260902f338e23d06499790c6948709afb1587416eb40Makoto Onuki wtf("Exception in mPackageMonitor.onReceive", e); 26104e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } finally { 26114e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki injectRestoreCallingIdentity(token); 26124e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki } 2613f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki } 2614f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki }; 2615cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 26160acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki /** 261739686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki * Called when a user is unlocked. 261839686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki * - Check all known packages still exist, and otherwise perform cleanup. 261939686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki * - If a package still exists, check the version code. If it's been updated, may need to 2620b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki * update timestamps of its shortcuts. 26210acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki */ 2622d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki @VisibleForTesting 262339686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki void checkPackageChanges(@UserIdInt int ownerUserId) { 26240acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki if (DEBUG) { 262539686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki Slog.d(TAG, "checkPackageChanges() ownerUserId=" + ownerUserId); 2626cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2627b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki if (injectIsSafeModeEnabled()) { 2628b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki Slog.i(TAG, "Safe mode, skipping checkPackageChanges()"); 2629b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki return; 2630b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 26310acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 263222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final long start = injectElapsedRealtime(); 263322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki try { 263422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final ArrayList<PackageWithUser> gonePackages = new ArrayList<>(); 26359da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 263622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki synchronized (mLock) { 263722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final ShortcutUser user = getUserShortcutsLocked(ownerUserId); 263822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 263922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki // Find packages that have been uninstalled. 264022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki user.forAllPackageItems(spi -> { 264122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (spi.getPackageInfo().isShadow()) { 264222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return; // Don't delete shadow information. 264322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 264422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (!isPackageInstalled(spi.getPackageName(), spi.getPackageUserId())) { 2645ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (DEBUG) { 2646ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki Slog.d(TAG, "Uninstalled: " + spi.getPackageName() 2647ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki + " user " + spi.getPackageUserId()); 2648ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 264922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki gonePackages.add(PackageWithUser.of(spi)); 265022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 265122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki }); 265222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (gonePackages.size() > 0) { 265322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki for (int i = gonePackages.size() - 1; i >= 0; i--) { 265422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final PackageWithUser pu = gonePackages.get(i); 2655b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki cleanUpPackageLocked(pu.packageName, ownerUserId, pu.userId, 2656b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki /* appStillExists = */ false); 265722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 2658905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki } 265922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 2660377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki rescanUpdatedPackagesLocked(ownerUserId, user.getLastAppScanTime(), 2661377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki /* forceRescan=*/ false); 26620acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 266322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } finally { 266422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki logDurationStat(Stats.CHECK_PACKAGE_CHANGES, start); 26650acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 26669e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki verifyStates(); 26670acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 2668cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 2669377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki private void rescanUpdatedPackagesLocked(@UserIdInt int userId, long lastScanTime, 2670377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki boolean forceRescan) { 2671377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki final ShortcutUser user = getUserShortcutsLocked(userId); 2672377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki 26733366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki // Note after each OTA, we'll need to rescan all system apps, as their lastUpdateTime 26743366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki // is not reliable. 2675377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki final long now = injectCurrentTimeMillis(); 26763366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki final boolean afterOta = 26773366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki !injectBuildFingerprint().equals(user.getLastAppScanOsFingerprint()); 2678377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki 2679377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki // Then for each installed app, publish manifest shortcuts when needed. 26803366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki forUpdatedPackages(userId, lastScanTime, afterOta, ai -> { 2681377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki user.attemptToRestoreIfNeededAndSave(this, ai.packageName, userId); 2682377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki user.rescanPackageIfNeeded(ai.packageName, forceRescan); 2683377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki }); 2684377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki 2685377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki // Write the time just before the scan, because there may be apps that have just 2686377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki // been updated, and we want to catch them in the next time. 2687377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki user.setLastAppScanTime(now); 26883366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki user.setLastAppScanOsFingerprint(injectBuildFingerprint()); 2689377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki scheduleSaveUser(userId); 2690377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki } 2691377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki 26920acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki private void handlePackageAdded(String packageName, @UserIdInt int userId) { 2693cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki if (DEBUG) { 26940acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki Slog.d(TAG, String.format("handlePackageAdded: %s user=%d", packageName, userId)); 26950acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 26960acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki synchronized (mLock) { 269722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final ShortcutUser user = getUserShortcutsLocked(userId); 269822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki user.attemptToRestoreIfNeededAndSave(this, packageName, userId); 269964183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ true); 2700cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 27019e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki verifyStates(); 2702cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2703cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 27040acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki private void handlePackageUpdateFinished(String packageName, @UserIdInt int userId) { 2705905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki if (DEBUG) { 27069da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki Slog.d(TAG, String.format("handlePackageUpdateFinished: %s user=%d", 27079da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki packageName, userId)); 27080acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 27090acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki synchronized (mLock) { 271022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final ShortcutUser user = getUserShortcutsLocked(userId); 271122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki user.attemptToRestoreIfNeededAndSave(this, packageName, userId); 271239686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki 271322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki if (isPackageInstalled(packageName, userId)) { 271464183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ true); 271539686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki } 27160acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 27179e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki verifyStates(); 27180acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 27190acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 27202e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki private void handlePackageRemoved(String packageName, @UserIdInt int packageUserId) { 2721cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki if (DEBUG) { 27222e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName, 27232e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki packageUserId)); 2724cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2725b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki cleanUpPackageForAllLoadedUsers(packageName, packageUserId, /* appStillExists = */ false); 27269e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 27279e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki verifyStates(); 27285ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki } 27295ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 27309ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki private void handlePackageDataCleared(String packageName, int packageUserId) { 27319ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki if (DEBUG) { 27329ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki Slog.d(TAG, String.format("handlePackageDataCleared: %s user=%d", packageName, 27339ac59d0438833eee817e4b4e5c03ce5ec8fcf4dcMakoto Onuki packageUserId)); 2734cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2735b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki cleanUpPackageForAllLoadedUsers(packageName, packageUserId, /* appStillExists = */ true); 2736b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 2737b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki verifyStates(); 2738b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 2739b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 2740b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki private void handlePackageChanged(String packageName, int packageUserId) { 2741b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki if (DEBUG) { 2742b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki Slog.d(TAG, String.format("handlePackageChanged: %s user=%d", packageName, 2743b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki packageUserId)); 2744b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 2745b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 2746b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki // Activities may be disabled or enabled. Just rescan the package. 2747b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki synchronized (mLock) { 2748b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final ShortcutUser user = getUserShortcutsLocked(packageUserId); 2749b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 27504e6cef49ef11bbb5bfc0e9f0fb865188492d88b0Makoto Onuki user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ true); 2751b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 27529e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki 27539e1f5595bd7ffe3af6ca35b3235dfca0ecd07978Makoto Onuki verifyStates(); 2754cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 2755cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 27569da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki // === PackageManager interaction === 27570acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 2758ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2759ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Returns {@link PackageInfo} unless it's uninstalled or disabled. 2760ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 276122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @Nullable 2762ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final PackageInfo getPackageInfoWithSignatures(String packageName, @UserIdInt int userId) { 2763ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return getPackageInfo(packageName, userId, true); 27640acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 27650acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 2766ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2767ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Returns {@link PackageInfo} unless it's uninstalled or disabled. 2768ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 276922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @Nullable 2770ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final PackageInfo getPackageInfo(String packageName, @UserIdInt int userId) { 2771ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return getPackageInfo(packageName, userId, false); 277222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 277322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 2774905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki int injectGetPackageUid(@NonNull String packageName, @UserIdInt int userId) { 27759da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final long token = injectClearCallingIdentity(); 2776905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki try { 2777ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return mIPackageManager.getPackageUid(packageName, PACKAGE_MATCH_FLAGS, userId); 2778905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki } catch (RemoteException e) { 2779905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki // Shouldn't happen. 2780905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki Slog.wtf(TAG, "RemoteException", e); 2781905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki return -1; 27829da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } finally { 27839da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki injectRestoreCallingIdentity(token); 2784905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki } 27850acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 27860acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 2787ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2788ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Returns {@link PackageInfo} unless it's uninstalled or disabled. 2789ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 279022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @Nullable 27910acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki @VisibleForTesting 2792ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final PackageInfo getPackageInfo(String packageName, @UserIdInt int userId, 2793ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki boolean getSignatures) { 2794ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return isInstalledOrNull(injectPackageInfoWithUninstalled( 2795ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki packageName, userId, getSignatures)); 2796ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2797ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2798ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2799ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Do not use directly; this returns uninstalled packages too. 2800ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 2801ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @Nullable 2802ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @VisibleForTesting 2803ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki PackageInfo injectPackageInfoWithUninstalled(String packageName, @UserIdInt int userId, 28040acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki boolean getSignatures) { 28056c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final long start = injectElapsedRealtime(); 28069da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final long token = injectClearCallingIdentity(); 28070acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki try { 2808ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return mIPackageManager.getPackageInfo( 2809ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki packageName, PACKAGE_MATCH_FLAGS 2810ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki | (getSignatures ? PackageManager.GET_SIGNATURES : 0), userId); 28110acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } catch (RemoteException e) { 28120acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki // Shouldn't happen. 28130acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki Slog.wtf(TAG, "RemoteException", e); 28140acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki return null; 28159da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } finally { 28169da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki injectRestoreCallingIdentity(token); 28172e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 28182e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki logDurationStat( 28192e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki (getSignatures ? Stats.GET_PACKAGE_INFO_WITH_SIG : Stats.GET_PACKAGE_INFO), 28202e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki start); 28210acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 28220acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 28230acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki 2824ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2825ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Returns {@link ApplicationInfo} unless it's uninstalled or disabled. 2826ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 282722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @Nullable 2828905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki @VisibleForTesting 2829ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final ApplicationInfo getApplicationInfo(String packageName, @UserIdInt int userId) { 2830ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return isInstalledOrNull(injectApplicationInfoWithUninstalled(packageName, userId)); 2831ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2832ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2833ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2834ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Do not use directly; this returns uninstalled packages too. 2835ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 2836ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @Nullable 2837ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @VisibleForTesting 2838ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki ApplicationInfo injectApplicationInfoWithUninstalled( 2839ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki String packageName, @UserIdInt int userId) { 28406c1dbd577bcf2b8bccb9a0d04d741ff7337898f2Makoto Onuki final long start = injectElapsedRealtime(); 28419da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final long token = injectClearCallingIdentity(); 2842905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki try { 2843905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki return mIPackageManager.getApplicationInfo(packageName, PACKAGE_MATCH_FLAGS, userId); 2844905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki } catch (RemoteException e) { 2845905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki // Shouldn't happen. 2846905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki Slog.wtf(TAG, "RemoteException", e); 2847905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki return null; 28489da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } finally { 28499da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki injectRestoreCallingIdentity(token); 28502e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 28512e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki logDurationStat(Stats.GET_APPLICATION_INFO, start); 2852905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki } 2853905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki } 2854905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki 2855ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2856ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Returns {@link ActivityInfo} with its metadata unless it's uninstalled or disabled. 2857ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 2858ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @Nullable 2859ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final ActivityInfo getActivityInfoWithMetadata(ComponentName activity, @UserIdInt int userId) { 2860ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return isInstalledOrNull(injectGetActivityInfoWithMetadataWithUninstalled( 2861ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki activity, userId)); 2862ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2863ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2864ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2865ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Do not use directly; this returns uninstalled packages too. 2866ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 286722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @Nullable 2868ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @VisibleForTesting 2869ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki ActivityInfo injectGetActivityInfoWithMetadataWithUninstalled( 2870ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki ComponentName activity, @UserIdInt int userId) { 287122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final long start = injectElapsedRealtime(); 287222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final long token = injectClearCallingIdentity(); 287322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki try { 2874b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki return mIPackageManager.getActivityInfo(activity, 2875ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki (PACKAGE_MATCH_FLAGS | PackageManager.GET_META_DATA), userId); 287622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } catch (RemoteException e) { 287722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki // Shouldn't happen. 287822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki Slog.wtf(TAG, "RemoteException", e); 287922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return null; 288022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } finally { 288122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki injectRestoreCallingIdentity(token); 288222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 2883b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki logDurationStat(Stats.GET_ACTIVITY_WITH_METADATA, start); 288422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 288522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 288622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 2887ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2888ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Return all installed and enabled packages. 2889ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 2890ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @NonNull 289122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @VisibleForTesting 2892ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final List<PackageInfo> getInstalledPackages(@UserIdInt int userId) { 289322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final long start = injectElapsedRealtime(); 289422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki final long token = injectClearCallingIdentity(); 289522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki try { 2896ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final List<PackageInfo> all = injectGetPackagesWithUninstalled(userId); 2897ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2898ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki all.removeIf(PACKAGE_NOT_INSTALLED); 2899ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2900ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return all; 290122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } catch (RemoteException e) { 290222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki // Shouldn't happen. 290322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki Slog.wtf(TAG, "RemoteException", e); 290422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return null; 290522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } finally { 290622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki injectRestoreCallingIdentity(token); 290722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 29086dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki logDurationStat(Stats.GET_INSTALLED_PACKAGES, start); 290922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 291022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 291122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 2912ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 2913ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Do not use directly; this returns uninstalled packages too. 2914ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 2915ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @NonNull 2916ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @VisibleForTesting 2917ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki List<PackageInfo> injectGetPackagesWithUninstalled(@UserIdInt int userId) 2918ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki throws RemoteException { 2919ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final ParceledListSlice<PackageInfo> parceledList = 2920ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki mIPackageManager.getInstalledPackages(PACKAGE_MATCH_FLAGS, userId); 2921ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (parceledList == null) { 2922ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return Collections.emptyList(); 2923ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2924ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return parceledList.getList(); 2925ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2926ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 29273366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki private void forUpdatedPackages(@UserIdInt int userId, long lastScanTime, boolean afterOta, 292822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki Consumer<ApplicationInfo> callback) { 29296dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki if (DEBUG) { 29306dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki Slog.d(TAG, "forUpdatedPackages for user " + userId + ", lastScanTime=" + lastScanTime); 29316dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki } 2932ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final List<PackageInfo> list = getInstalledPackages(userId); 293322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki for (int i = list.size() - 1; i >= 0; i--) { 29346dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki final PackageInfo pi = list.get(i); 293522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 293664183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki // If the package has been updated since the last scan time, then scan it. 293764183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki // Also if it's a system app with no update, lastUpdateTime is not reliable, so 293864183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki // just scan it. 29393366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki if (pi.lastUpdateTime >= lastScanTime 29403366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki || (afterOta && isPureSystemApp(pi.applicationInfo))) { 29416dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki if (DEBUG) { 29426dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki Slog.d(TAG, "Found updated package " + pi.packageName); 29436dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki } 29446dd9fb7004e888ec1efc4676cd3e4d42b7ac68c9Makoto Onuki callback.accept(pi.applicationInfo); 294522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 294622fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 294722fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 294822fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 294964183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki /** 295064183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki * @return true if it's a system app with no updates. 295164183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki */ 295264183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki private boolean isPureSystemApp(ApplicationInfo ai) { 295364183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki return ai.isSystemApp() && !ai.isUpdatedSystemApp(); 295464183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki } 295564183d518813cc65efcaeaf0d4c28de092b32868Makoto Onuki 2956ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private boolean isApplicationFlagSet(@NonNull String packageName, int userId, int flags) { 2957ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final ApplicationInfo ai = injectApplicationInfoWithUninstalled(packageName, userId); 2958905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki return (ai != null) && ((ai.flags & flags) == flags); 2959905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki } 2960905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki 2961ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static boolean isInstalled(@Nullable ApplicationInfo ai) { 2962ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return (ai != null) && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0; 2963ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2964ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2965ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static boolean isInstalled(@Nullable PackageInfo pi) { 2966ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return (pi != null) && isInstalled(pi.applicationInfo); 2967ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2968ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2969ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static boolean isInstalled(@Nullable ActivityInfo ai) { 2970ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return (ai != null) && isInstalled(ai.applicationInfo); 2971ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2972ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2973ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static ApplicationInfo isInstalledOrNull(ApplicationInfo ai) { 2974ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return isInstalled(ai) ? ai : null; 2975ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2976ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2977ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static PackageInfo isInstalledOrNull(PackageInfo pi) { 2978ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return isInstalled(pi) ? pi : null; 2979ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2980ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 2981ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki private static ActivityInfo isInstalledOrNull(ActivityInfo ai) { 2982ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return isInstalled(ai) ? ai : null; 2983ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 2984ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 29852e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki boolean isPackageInstalled(String packageName, int userId) { 2986ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return getApplicationInfo(packageName, userId) != null; 29879da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 29889da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 298922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @Nullable 299022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) { 299122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return activityInfo.loadXmlMetaData(mContext.getPackageManager(), key); 299239686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki } 299339686e8cdec3550c941d376929084f59ac0d78cdMakoto Onuki 2994157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki @Nullable 2995157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki Resources injectGetResourcesForApplicationAsUser(String packageName, int userId) { 2996157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki final long start = injectElapsedRealtime(); 2997157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki final long token = injectClearCallingIdentity(); 2998157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki try { 2999157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki return mContext.getPackageManager().getResourcesForApplicationAsUser( 3000157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki packageName, userId); 3001157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } catch (NameNotFoundException e) { 3002157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki Slog.e(TAG, "Resources for package " + packageName + " not found"); 3003157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki return null; 3004157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } finally { 3005157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki injectRestoreCallingIdentity(token); 3006157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki 3007157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki logDurationStat(Stats.GET_APPLICATION_RESOURCES, start); 3008157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } 3009157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki } 3010157b1628fd84dc3ef0355fddd8d281618f94d33eMakoto Onuki 3011b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki private Intent getMainActivityIntent() { 3012b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final Intent intent = new Intent(Intent.ACTION_MAIN); 3013b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki intent.addCategory(LAUNCHER_INTENT_CATEGORY); 3014b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki return intent; 3015b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3016b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3017ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 3018ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Same as queryIntentActivitiesAsUser, except it makes sure the package is installed, 3019ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * and only returns exported activities. 3020ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 3021ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @NonNull 3022ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @VisibleForTesting 3023ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki List<ResolveInfo> queryActivities(@NonNull Intent baseIntent, 3024ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @NonNull String packageName, @Nullable ComponentName activity, int userId) { 3025ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 3026ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki baseIntent.setPackage(Preconditions.checkNotNull(packageName)); 3027ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (activity != null) { 3028ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki baseIntent.setComponent(activity); 3029ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 3030ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 3031ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final List<ResolveInfo> resolved = 3032ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki mContext.getPackageManager().queryIntentActivitiesAsUser( 3033ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki baseIntent, PACKAGE_MATCH_FLAGS, userId); 3034ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (resolved == null || resolved.size() == 0) { 3035ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return EMPTY_RESOLVE_INFO; 3036ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 3037ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki // Make sure the package is installed. 3038ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki if (!isInstalled(resolved.get(0).activityInfo)) { 3039ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return EMPTY_RESOLVE_INFO; 3040ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 3041ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki resolved.removeIf(ACTIVITY_NOT_EXPORTED); 3042ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return resolved; 3043ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 3044ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki 3045ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 3046ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Return the main activity that is enabled and exported. If multiple activities are found, 3047ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * return the first one. 3048ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 3049b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki @Nullable 3050b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki ComponentName injectGetDefaultMainActivity(@NonNull String packageName, int userId) { 3051b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final long start = injectElapsedRealtime(); 3052b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final long token = injectClearCallingIdentity(); 3053b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki try { 3054b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final List<ResolveInfo> resolved = 3055ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki queryActivities(getMainActivityIntent(), packageName, null, userId); 3056ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return resolved.size() == 0 ? null : resolved.get(0).activityInfo.getComponentName(); 3057b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } finally { 3058b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki injectRestoreCallingIdentity(token); 3059b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3060b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki logDurationStat(Stats.GET_LAUNCHER_ACTIVITY, start); 3061b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3062b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3063b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3064ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 3065ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Return whether an activity is enabled, exported and main. 3066ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 3067b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki boolean injectIsMainActivity(@NonNull ComponentName activity, int userId) { 3068b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final long start = injectElapsedRealtime(); 3069b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final long token = injectClearCallingIdentity(); 3070b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki try { 3071b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final List<ResolveInfo> resolved = 3072ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki queryActivities(getMainActivityIntent(), activity.getPackageName(), 3073ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki activity, userId); 3074ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return resolved.size() > 0; 3075b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } finally { 3076b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki injectRestoreCallingIdentity(token); 3077b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3078b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki logDurationStat(Stats.CHECK_LAUNCHER_ACTIVITY, start); 3079b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3080b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3081b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3082ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 3083ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Return all the enabled, exported and main activities from a package. 3084ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 3085b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki @NonNull 3086b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki List<ResolveInfo> injectGetMainActivities(@NonNull String packageName, int userId) { 3087b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final long start = injectElapsedRealtime(); 3088b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final long token = injectClearCallingIdentity(); 3089b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki try { 3090ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return queryActivities(getMainActivityIntent(), packageName, null, userId); 3091ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } finally { 3092ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki injectRestoreCallingIdentity(token); 3093b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3094ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki logDurationStat(Stats.CHECK_LAUNCHER_ACTIVITY, start); 3095ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 3096ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki } 3097b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3098ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki /** 3099ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki * Return whether an activity is enabled and exported. 3100ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki */ 3101ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @VisibleForTesting 3102ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki boolean injectIsActivityEnabledAndExported( 3103ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki @NonNull ComponentName activity, @UserIdInt int userId) { 3104ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final long start = injectElapsedRealtime(); 3105ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki final long token = injectClearCallingIdentity(); 3106ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki try { 3107ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki return queryActivities(new Intent(), activity.getPackageName(), activity, userId) 3108ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki .size() > 0; 3109b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } finally { 3110b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki injectRestoreCallingIdentity(token); 3111b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3112ee6b6e4a1861336f8db52d8c93dbf32ee9615cfaMakoto Onuki logDurationStat(Stats.IS_ACTIVITY_ENABLED, start); 3113b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3114b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3115b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3116b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki boolean injectIsSafeModeEnabled() { 3117b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki final long token = injectClearCallingIdentity(); 3118b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki try { 3119b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki return IWindowManager.Stub 3120b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE)) 3121b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki .isSafeModeEnabled(); 3122b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } catch (RemoteException e) { 3123b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki return false; // Shouldn't happen though. 3124b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } finally { 3125b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki injectRestoreCallingIdentity(token); 3126b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3127b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3128b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 31299da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki // === Backup & restore === 31309da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 31310acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki boolean shouldBackupApp(String packageName, int userId) { 3132905e8855e7df111f835fecde32598479058fe4dfMakoto Onuki return isApplicationFlagSet(packageName, userId, ApplicationInfo.FLAG_ALLOW_BACKUP); 31330acbb14574d859b5f1cc0b7c6bbdfbeba38f3e55Makoto Onuki } 3134cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 31352e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki boolean shouldBackupApp(PackageInfo pi) { 31362e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki return (pi.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0; 31372e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 31382e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 31399da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki @Override 31402e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki public byte[] getBackupPayload(@UserIdInt int userId) { 31419da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki enforceSystem(); 31429da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki if (DEBUG) { 31439da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki Slog.d(TAG, "Backing up user " + userId); 31449da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 31459da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki synchronized (mLock) { 314602f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(userId)) { 314702f338e23d06499790c6948709afb1587416eb40Makoto Onuki wtf("Can't backup: user " + userId + " is locked or not running"); 314802f338e23d06499790c6948709afb1587416eb40Makoto Onuki return null; 314902f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 315002f338e23d06499790c6948709afb1587416eb40Makoto Onuki 31519da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final ShortcutUser user = getUserShortcutsLocked(userId); 31529da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki if (user == null) { 315302f338e23d06499790c6948709afb1587416eb40Makoto Onuki wtf("Can't backup: user not found: id=" + userId); 31549da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki return null; 31559da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 31569da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 3157c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki // Update the signatures for all packages. 3158c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki user.forAllPackageItems(spi -> spi.refreshPackageSignatureAndSave()); 3159c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki 3160c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki // Set the version code for the launchers. 3161c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki // We shouldn't do this for publisher packages, because we don't want to update the 3162c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki // version code without rescanning the manifest. 3163c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki user.forAllLaunchers(launcher -> launcher.ensureVersionInfo()); 3164c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki 3165c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki // Save to the filesystem. 3166c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki scheduleSaveUser(userId); 3167c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki saveDirtyInfo(); 31689da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 3169c8c3329dd918b8ea16d6317d19ddee12325800f3Makoto Onuki // Then create the backup payload. 31709da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki final ByteArrayOutputStream os = new ByteArrayOutputStream(32 * 1024); 31719da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki try { 31729da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki saveUserInternalLocked(userId, os, /* forBackup */ true); 3173b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } catch (XmlPullParserException | IOException e) { 31749da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki // Shouldn't happen. 31759da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki Slog.w(TAG, "Backup failed.", e); 31769da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki return null; 31779da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 31789da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki return os.toByteArray(); 31799da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 31809da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 31819da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki 31829da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki @Override 31832e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki public void applyRestore(byte[] payload, @UserIdInt int userId) { 31849da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki enforceSystem(); 31859da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki if (DEBUG) { 31869da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki Slog.d(TAG, "Restoring user " + userId); 31879da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 31889da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki synchronized (mLock) { 318902f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(userId)) { 319002f338e23d06499790c6948709afb1587416eb40Makoto Onuki wtf("Can't restore: user " + userId + " is locked or not running"); 319102f338e23d06499790c6948709afb1587416eb40Makoto Onuki return; 319202f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 3193fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki // Actually do restore. 3194fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki final ShortcutUser restored; 319502f338e23d06499790c6948709afb1587416eb40Makoto Onuki final ByteArrayInputStream is = new ByteArrayInputStream(payload); 319602f338e23d06499790c6948709afb1587416eb40Makoto Onuki try { 3197fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki restored = loadUserInternal(userId, is, /* fromBackup */ true); 3198fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki } catch (XmlPullParserException | IOException | InvalidFileFormatException e) { 319902f338e23d06499790c6948709afb1587416eb40Makoto Onuki Slog.w(TAG, "Restoration failed.", e); 320002f338e23d06499790c6948709afb1587416eb40Makoto Onuki return; 320102f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 3202fc4cf2da34335fd7e84c020f51eea1a341d3f134Makoto Onuki getUserShortcutsLocked(userId).mergeRestoredFile(restored); 32032e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 3204377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki // Rescan all packages to re-publish manifest shortcuts and do other checks. 3205377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki rescanUpdatedPackagesLocked(userId, 3206377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki 0, // lastScanTime = 0; rescan all packages. 3207377b7970ad70e87f8137ea7d9e7a6b00de1826aeMakoto Onuki /* forceRescan= */ true); 32082e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 32092e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki saveUserLocked(userId); 32109da23fc6ac565b38129d52f4f8f174c833a9bd01Makoto Onuki } 3211cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki } 3212cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 32136f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // === Dump === 32146f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 32156f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 32166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 321776269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, 321876269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki "can't dump by this caller"); 321976269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki boolean checkin = false; 322076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki boolean clear = false; 322176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki if (args != null) { 322276269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki for (String arg : args) { 322376269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki if ("-c".equals(arg)) { 322476269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki checkin = true; 322576269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } else if ("--checkin".equals(arg)) { 322676269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki checkin = true; 322776269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki clear = true; 322876269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 322976269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 323076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 323176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 323276269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki if (checkin) { 323376269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki dumpCheckin(pw, clear); 323476269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } else { 323576269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki dumpInner(pw); 32366f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 32376f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 32386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 323976269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki private void dumpInner(PrintWriter pw) { 32406f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki synchronized (mLock) { 32416f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final long now = injectCurrentTimeMillis(); 32426f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print("Now: ["); 32436f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(now); 32446f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print("] "); 32456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(formatTime(now)); 32465504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 32476f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(" Raw last reset: ["); 32486f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(mRawLastResetTime); 32496f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print("] "); 32506f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(formatTime(mRawLastResetTime)); 32516f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 32526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final long last = getLastResetTimeLocked(); 32536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(" Last reset: ["); 32546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(last); 32556f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print("] "); 32566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(formatTime(last)); 32576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 32585504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki final long next = getNextResetTimeLocked(); 32596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(" Next reset: ["); 32606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(next); 32616f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print("] "); 32626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.print(formatTime(next)); 32634d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 32645ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.print(" Config:"); 32655ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.print(" Max icon dim: "); 32665ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println(mMaxIconDimension); 32675ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.print(" Icon format: "); 32685ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println(mIconPersistFormat); 32695ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.print(" Icon quality: "); 32702e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.println(mIconPersistQuality); 32710033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki pw.print(" saveDelayMillis: "); 32725ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println(mSaveDelayMillis); 32730033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki pw.print(" resetInterval: "); 32745ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println(mResetInterval); 32750033b2a190feeda8b41dd62b489aca3a19a09d5bMakoto Onuki pw.print(" maxUpdatesPerInterval: "); 3276b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki pw.println(mMaxUpdatesPerInterval); 3277b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki pw.print(" maxShortcutsPerActivity: "); 3278b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki pw.println(mMaxShortcuts); 32795504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki pw.println(); 32805504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 32812e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.println(" Stats:"); 32822e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki synchronized (mStatLock) { 3283085a05cd864252314bcf5c339017a16b68105204Makoto Onuki for (int i = 0; i < Stats.COUNT; i++) { 3284085a05cd864252314bcf5c339017a16b68105204Makoto Onuki dumpStatLS(pw, " ", i); 3285085a05cd864252314bcf5c339017a16b68105204Makoto Onuki } 32862e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 32876f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 3288a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki pw.println(); 3289a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki pw.print(" #Failures: "); 3290a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki pw.println(mWtfCount); 3291a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki 3292a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki if (mLastWtfStacktrace != null) { 3293a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki pw.print(" Last failure stack trace: "); 3294a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki pw.println(Log.getStackTraceString(mLastWtfStacktrace)); 3295a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki } 3296a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki 32973f4b1ca97ad7c31bdbe2ba29264841fb58683e81Makoto Onuki for (int i = 0; i < mUsers.size(); i++) { 32983f4b1ca97ad7c31bdbe2ba29264841fb58683e81Makoto Onuki pw.println(); 3299c51b2876ec5c0af449469a0f76bb38c51cfcff04Makoto Onuki mUsers.valueAt(i).dump(pw, " "); 33006f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 33014d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 33024d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.println(); 33034d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.println(" UID state:"); 33044d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 33054d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki for (int i = 0; i < mUidState.size(); i++) { 33064d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki final int uid = mUidState.keyAt(i); 33074d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki final int state = mUidState.valueAt(i); 33084d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.print(" UID="); 33094d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.print(uid); 33104d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.print(" state="); 33114d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.print(state); 33124d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki if (isProcessStateForeground(state)) { 33134d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.print(" [FG]"); 33144d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 33154d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.print(" last FG="); 33164d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.print(mUidLastForegroundElapsedTime.get(uid)); 33174d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki pw.println(); 33184d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 33196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 33206f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 33216f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 332241066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki static String formatTime(long time) { 33236f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Time tobj = new Time(); 33246f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki tobj.set(time); 33256f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return tobj.format("%Y-%m-%d %H:%M:%S"); 33266f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 33276f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 3328085a05cd864252314bcf5c339017a16b68105204Makoto Onuki private void dumpStatLS(PrintWriter pw, String prefix, int statId) { 33292e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.print(prefix); 33302e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final int count = mCountStats[statId]; 33312e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki final long dur = mDurationStats[statId]; 33322e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki pw.println(String.format("%s: count=%d, total=%dms, avg=%.1fms", 3333085a05cd864252314bcf5c339017a16b68105204Makoto Onuki STAT_LABELS[statId], count, dur, 33342e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki (count == 0 ? 0 : ((double) dur) / count))); 33352e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki } 33362e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki 333776269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki /** 333876269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki * Dumpsys for checkin. 333976269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki * 334076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki * @param clear if true, clear the history information. Some other system services have this 334176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki * behavior but shortcut service doesn't for now. 334276269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki */ 334376269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki private void dumpCheckin(PrintWriter pw, boolean clear) { 334476269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki synchronized (mLock) { 334576269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki try { 334676269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki final JSONArray users = new JSONArray(); 334776269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 334876269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki for (int i = 0; i < mUsers.size(); i++) { 334976269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki users.put(mUsers.valueAt(i).dumpCheckin(clear)); 335076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 335176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 335276269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki final JSONObject result = new JSONObject(); 335376269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 335476269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki result.put(KEY_SHORTCUT, users); 335576269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki result.put(KEY_LOW_RAM, injectIsLowRamDevice()); 335676269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki result.put(KEY_ICON_SIZE, mMaxIconDimension); 335776269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 335876269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki pw.println(result.toString(1)); 335976269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } catch (JSONException e) { 336076269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki Slog.e(TAG, "Unable to write in json", e); 336176269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 336276269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 336376269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki } 336476269928e677725e2d9b28e2e3aa79961a60a1d0Makoto Onuki 33656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // === Shell support === 33666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 33676f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 33686f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 33696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki String[] args, ResultReceiver resultReceiver) throws RemoteException { 33706f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 33716f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki enforceShell(); 33726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 33730b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki final long token = injectClearCallingIdentity(); 33740b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki try { 33750b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki final int status = (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver); 33760b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki resultReceiver.send(status, null); 33770b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki } finally { 33780b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki injectRestoreCallingIdentity(token); 33790b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki } 33806f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 33816f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 33822d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki static class CommandException extends Exception { 33832d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki public CommandException(String message) { 33842d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki super(message); 33852d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 33862d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 33872d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 33886f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki /** 33896f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * Handle "adb shell cmd". 33906f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki */ 33916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private class MyShellCommand extends ShellCommand { 33922d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 33932d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private int mUserId = UserHandle.USER_SYSTEM; 33942d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 339502f338e23d06499790c6948709afb1587416eb40Makoto Onuki private void parseOptionsLocked(boolean takeUser) 33962d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki throws CommandException { 33972d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki String opt; 33982d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki while ((opt = getNextOption()) != null) { 33992d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki switch (opt) { 34002d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki case "--user": 34012d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki if (takeUser) { 34022d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki mUserId = UserHandle.parseUserArg(getNextArgRequired()); 340302f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isUserUnlockedL(mUserId)) { 3404f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki throw new CommandException( 3405f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki "User " + mUserId + " is not running or locked"); 3406f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki } 34072d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki break; 34082d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 34092d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // fallthrough 34102d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki default: 34112d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki throw new CommandException("Unknown option: " + opt); 34122d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 34132d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 34142d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 34152d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 34166f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 34176f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public int onCommand(String cmd) { 34186f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (cmd == null) { 34196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return handleDefaultCommands(cmd); 34206f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 34216f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final PrintWriter pw = getOutPrintWriter(); 34222d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki try { 34232d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki switch (cmd) { 34242d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki case "reset-throttling": 34252d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki handleResetThrottling(); 34262d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki break; 34275ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki case "reset-all-throttling": 34285ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki handleResetAllThrottling(); 34295ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki break; 34302d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki case "override-config": 34312d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki handleOverrideConfig(); 34322d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki break; 34332d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki case "reset-config": 34342d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki handleResetConfig(); 34352d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki break; 34362d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki case "clear-default-launcher": 34372d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki handleClearDefaultLauncher(); 34382d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki break; 34392d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki case "get-default-launcher": 34402d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki handleGetDefaultLauncher(); 34412d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki break; 3442ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki case "unload-user": 3443ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki handleUnloadUser(); 3444ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki break; 34455ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki case "clear-shortcuts": 34465ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki handleClearShortcuts(); 34475ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki break; 3448b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki case "verify-states": // hidden command to verify various internal states. 3449b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki handleVerifyStates(); 3450b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki break; 34512d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki default: 34522d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki return handleDefaultCommands(cmd); 34532d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 34542d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } catch (CommandException e) { 34552d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki pw.println("Error: " + e.getMessage()); 34562d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki return 1; 34574362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 34582d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki pw.println("Success"); 34592d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki return 0; 34606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 34616f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 34626f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 34636f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void onHelp() { 34646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki final PrintWriter pw = getOutPrintWriter(); 34656f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.println("Usage: cmd shortcut COMMAND [options ...]"); 34666f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.println(); 34675ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println("cmd shortcut reset-throttling [--user USER_ID]"); 34686f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.println(" Reset throttling for all packages and users"); 34696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki pw.println(); 34705ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println("cmd shortcut reset-all-throttling"); 34715ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println(" Reset the throttling state for all users"); 34725ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println(); 34734362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki pw.println("cmd shortcut override-config CONFIG"); 34744362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki pw.println(" Override the configuration for testing (will last until reboot)"); 34754362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki pw.println(); 34764362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki pw.println("cmd shortcut reset-config"); 34774362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki pw.println(" Reset the configuration set with \"update-config\""); 34784362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki pw.println(); 34792d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki pw.println("cmd shortcut clear-default-launcher [--user USER_ID]"); 34802d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki pw.println(" Clear the cached default launcher"); 34812d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki pw.println(); 34822d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki pw.println("cmd shortcut get-default-launcher [--user USER_ID]"); 34830b9d1db5c1aab9017daf05abd0ba0f4de2c7192dMakoto Onuki pw.println(" Show the default launcher"); 34842d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki pw.println(); 3485ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki pw.println("cmd shortcut unload-user [--user USER_ID]"); 3486ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki pw.println(" Unload a user from the memory"); 3487ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki pw.println(" (This should not affect any observable behavior)"); 3488ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki pw.println(); 34895ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println("cmd shortcut clear-shortcuts [--user USER_ID] PACKAGE"); 34905ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println(" Remove all shortcuts from a package, including pinned shortcuts"); 34915ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki pw.println(); 34926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 34936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 34945ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki private void handleResetThrottling() throws CommandException { 349502f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 349602f338e23d06499790c6948709afb1587416eb40Makoto Onuki parseOptionsLocked(/* takeUser =*/ true); 34974554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki 349802f338e23d06499790c6948709afb1587416eb40Makoto Onuki Slog.i(TAG, "cmd: handleResetThrottling: user=" + mUserId); 34995ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 350002f338e23d06499790c6948709afb1587416eb40Makoto Onuki resetThrottlingInner(mUserId); 350102f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 35025ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki } 35035ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 35045ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki private void handleResetAllThrottling() { 35055ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki Slog.i(TAG, "cmd: handleResetAllThrottling"); 35065ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 35075ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki resetAllThrottlingInner(); 35086f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 35096f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 35102d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private void handleOverrideConfig() throws CommandException { 35114362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki final String config = getNextArgRequired(); 35124362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 35135ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki Slog.i(TAG, "cmd: handleOverrideConfig: " + config); 35145ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 35154362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki synchronized (mLock) { 35164362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki if (!updateConfigurationLocked(config)) { 35172d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki throw new CommandException("override-config failed. See logcat for details."); 35184362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 35194362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 35204362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 35214362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 35222d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private void handleResetConfig() { 35235ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki Slog.i(TAG, "cmd: handleResetConfig"); 35245ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 35254362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki synchronized (mLock) { 35264362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki loadConfigurationLocked(); 35274362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 35282d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 35292d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 35302d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private void clearLauncher() { 35312d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki synchronized (mLock) { 35321030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki getUserShortcutsLocked(mUserId).forceClearLauncher(); 35332d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 35342d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 35352d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 35362d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private void showLauncher() { 35372d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki synchronized (mLock) { 35382d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki // This ensures to set the cached launcher. Package name doesn't matter. 35392d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki hasShortcutHostPermissionInner("-", mUserId); 35402d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 35412d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki getOutPrintWriter().println("Launcher: " 35421030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki + getUserShortcutsLocked(mUserId).getLastKnownLauncher()); 35432d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 35442d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 35452d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 35462d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private void handleClearDefaultLauncher() throws CommandException { 354702f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 354802f338e23d06499790c6948709afb1587416eb40Makoto Onuki parseOptionsLocked(/* takeUser =*/ true); 35492d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 355002f338e23d06499790c6948709afb1587416eb40Makoto Onuki clearLauncher(); 355102f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 35522d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 35532d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 35542d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private void handleGetDefaultLauncher() throws CommandException { 355502f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 355602f338e23d06499790c6948709afb1587416eb40Makoto Onuki parseOptionsLocked(/* takeUser =*/ true); 35572d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 355802f338e23d06499790c6948709afb1587416eb40Makoto Onuki clearLauncher(); 355902f338e23d06499790c6948709afb1587416eb40Makoto Onuki showLauncher(); 356002f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 35614362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 3562ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki 3563ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki private void handleUnloadUser() throws CommandException { 356402f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 356502f338e23d06499790c6948709afb1587416eb40Makoto Onuki parseOptionsLocked(/* takeUser =*/ true); 3566ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki 356702f338e23d06499790c6948709afb1587416eb40Makoto Onuki Slog.i(TAG, "cmd: handleUnloadUser: user=" + mUserId); 35685ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 356902f338e23d06499790c6948709afb1587416eb40Makoto Onuki ShortcutService.this.handleCleanupUser(mUserId); 357002f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 3571ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 35725ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 35735ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki private void handleClearShortcuts() throws CommandException { 357402f338e23d06499790c6948709afb1587416eb40Makoto Onuki synchronized (mLock) { 357502f338e23d06499790c6948709afb1587416eb40Makoto Onuki parseOptionsLocked(/* takeUser =*/ true); 357602f338e23d06499790c6948709afb1587416eb40Makoto Onuki final String packageName = getNextArgRequired(); 35775ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 357802f338e23d06499790c6948709afb1587416eb40Makoto Onuki Slog.i(TAG, "cmd: handleClearShortcuts: user" + mUserId + ", " + packageName); 35795ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki 358002f338e23d06499790c6948709afb1587416eb40Makoto Onuki ShortcutService.this.cleanUpPackageForAllLoadedUsers(packageName, mUserId, 358102f338e23d06499790c6948709afb1587416eb40Makoto Onuki /* appStillExists = */ true); 358202f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 3583b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3584b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 3585b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki private void handleVerifyStates() throws CommandException { 3586b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki try { 3587b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki verifyStatesForce(); // This will throw when there's an issue. 3588b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } catch (Throwable th) { 3589b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki throw new CommandException(th.getMessage() + "\n" + Log.getStackTraceString(th)); 3590b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 35915ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki } 35926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 35936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 35946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // === Unit test support === 35956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 35966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Injection point. 35973145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki @VisibleForTesting 35986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki long injectCurrentTimeMillis() { 35996f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return System.currentTimeMillis(); 36006f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 36016f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 36024d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki @VisibleForTesting 36034d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki long injectElapsedRealtime() { 36044d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki return SystemClock.elapsedRealtime(); 36054d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 36064d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 36076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // Injection point. 36083145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki @VisibleForTesting 36096f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki int injectBinderCallingUid() { 36106f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return getCallingUid(); 36116f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 36126f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 36133145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki private int getCallingUserId() { 36144554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki return UserHandle.getUserId(injectBinderCallingUid()); 36154554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki } 36164554d0e5b69433ddaa698e976ee584f7f4f14948Makoto Onuki 36174dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki // Injection point. 36183145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki @VisibleForTesting 36194dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki long injectClearCallingIdentity() { 36204dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki return Binder.clearCallingIdentity(); 36214dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 36224dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki 36234dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki // Injection point. 36243145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki @VisibleForTesting 36254dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki void injectRestoreCallingIdentity(long token) { 36264dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki Binder.restoreCallingIdentity(token); 36274dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 36284dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki 36293366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki // Injection point. 36303366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki @VisibleForTesting 36313366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki String injectBuildFingerprint() { 36323366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki return Build.FINGERPRINT; 36333366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki } 36343366328245621fa6e8fd764a4d3c2f073774d096Makoto Onuki 3635de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki final void wtf(String message) { 3636b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki wtf(message, /* exception= */ null); 3637de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki } 3638de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki 36392e210c4d0f766e52ea4c087a1d54213c36a4e0eaMakoto Onuki // Injection point. 3640a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki void wtf(String message, Throwable e) { 3641a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki if (e == null) { 3642a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki e = new RuntimeException("Stacktrace"); 3643a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki } 3644a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki synchronized (mLock) { 3645a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki mWtfCount++; 3646a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki mLastWtfStacktrace = new Exception("Last failure was logged here:"); 3647a2241834a54dc91e2eef858741f1a56a743c27b2Makoto Onuki } 3648de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki Slog.wtf(TAG, message, e); 3649de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki } 3650de66737ae9c5d5c94155820fad65224a83d04c3dMakoto Onuki 36513145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki @VisibleForTesting 36526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki File injectSystemDataPath() { 36536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki return Environment.getDataSystemDirectory(); 36546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 36556f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 36563145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki @VisibleForTesting 36576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki File injectUserDataPath(@UserIdInt int userId) { 36585504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER); 36595504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 36605504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 36614362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 36625504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki boolean injectIsLowRamDevice() { 36635504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return ActivityManager.isLowRamDeviceStatic(); 36645504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 36655504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 36663145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki @VisibleForTesting 36674d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki void injectRegisterUidObserver(IUidObserver observer, int which) { 36684d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki try { 36694d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki ActivityManagerNative.getDefault().registerUidObserver(observer, which); 36704d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } catch (RemoteException shouldntHappen) { 36714d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 36724d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki } 36734d36b3a8c5ba1289d851ef337e46709bba333100Makoto Onuki 36745504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki File getUserBitmapFilePath(@UserIdInt int userId) { 36755504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS); 36766f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 36776f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 36786f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 36793145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki SparseArray<ShortcutUser> getShortcutsForTest() { 36803f4b1ca97ad7c31bdbe2ba29264841fb58683e81Makoto Onuki return mUsers; 36816f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 36826f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 36836f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 3684b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki int getMaxShortcutsForTest() { 3685b5a012fd6f088629746057a3902b5926f9fe8e08Makoto Onuki return mMaxShortcuts; 36864362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 36874362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 36884362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 3689b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki int getMaxUpdatesPerIntervalForTest() { 3690b6d3523dfb5d73ddda4b750a82c059cdc42acf8eMakoto Onuki return mMaxUpdatesPerInterval; 36914362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki } 36924362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki 36934362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki @VisibleForTesting 36944362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki long getResetIntervalForTest() { 36954362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki return mResetInterval; 36966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 36976f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 36986f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 36994362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki int getMaxIconDimensionForTest() { 37004362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki return mMaxIconDimension; 37016f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 37026f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 37036f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @VisibleForTesting 37044362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki CompressFormat getIconPersistFormatForTest() { 37054362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki return mIconPersistFormat; 37065504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 37075504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 37085504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @VisibleForTesting 37094362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki int getIconPersistQualityForTest() { 37104362a66dba0b4cfa9fadb6c8af10c590e4ba880dMakoto Onuki return mIconPersistQuality; 37116f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 371241066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki 371341066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki @VisibleForTesting 371422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ShortcutPackage getPackageShortcutForTest(String packageName, int userId) { 371541066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki synchronized (mLock) { 37163145924596ad0db9e8f1f5aead90fb50127243cbMakoto Onuki final ShortcutUser user = mUsers.get(userId); 3717cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki if (user == null) return null; 3718cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 371922fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki return user.getAllPackagesForTest().get(packageName); 372022fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 372122fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki } 372222fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki 372322fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki @VisibleForTesting 372422fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki ShortcutInfo getPackageShortcutForTest(String packageName, String shortcutId, int userId) { 372522fcc68e6be0edaa98f3dacf79d580a5e5d50005Makoto Onuki synchronized (mLock) { 3726f34c308dfd9cdda428b8ead8bf655de1608501a9Makoto Onuki final ShortcutPackage pkg = getPackageShortcutForTest(packageName, userId); 3727cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki if (pkg == null) return null; 3728cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki 3729cdc78f7137b8036dd96c92ff15fc04ee8fc49c5cMakoto Onuki return pkg.findShortcutById(shortcutId); 373041066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki } 373141066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki } 37327001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 37337001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki /** 37347001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki * Control whether {@link #verifyStates} should be performed. We always perform it during unit 37357001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki * tests. 37367001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki */ 37377001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki @VisibleForTesting 37387001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki boolean injectShouldPerformVerification() { 37397001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki return DEBUG; 37407001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki } 37417001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 37427001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki /** 37437001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki * Check various internal states and throws if there's any inconsistency. 37447001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki * This is normally only enabled during unit tests. 37457001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki */ 37467001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki final void verifyStates() { 37477001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki if (injectShouldPerformVerification()) { 37487001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki verifyStatesInner(); 37497001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki } 37507001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki } 37517001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki 3752b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki private final void verifyStatesForce() { 3753b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki verifyStatesInner(); 3754b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki } 3755b08790c3b2f3bdb0c2e2f7ff46e4584fb1127769Makoto Onuki 37567001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki private void verifyStatesInner() { 37571030520822c42cc7357b463d301c7e97e928ba22Makoto Onuki synchronized (mLock) { 37587001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates)); 37597001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki } 37607001a6154088c87a31d56641762ff0c2a48f1d57Makoto Onuki } 376141066a61b912f22dd0342a002b4b5e060719cec9Makoto Onuki} 3762