Loading services/core/java/com/android/server/pm/ShortcutLauncher.java +11 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.server.pm.ShortcutUser.PackageWithUser; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading Loading @@ -288,6 +290,15 @@ class ShortcutLauncher extends ShortcutPackageItem { } } @Override public JSONObject dumpCheckin(boolean clear) throws JSONException { final JSONObject result = super.dumpCheckin(clear); // Nothing really interesting to dump. return result; } @VisibleForTesting ArraySet<String> getAllPinnedShortcutsForTest(String packageName, int packageUserId) { return new ArraySet<>(mPinnedShortcuts.get(PackageWithUser.of(packageUserId, packageName))); Loading services/core/java/com/android/server/pm/ShortcutPackage.java +44 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ import com.android.internal.util.XmlUtils; import com.android.server.pm.ShortcutService.ShortcutOperation; import com.android.server.pm.ShortcutService.Stats; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading Loading @@ -93,6 +95,12 @@ class ShortcutPackage extends ShortcutPackageItem { private static final String TAG_STRING_ARRAY_XMLUTILS = "string-array"; private static final String ATTR_NAME_XMLUTILS = "name"; private static final String KEY_DYNAMIC = "dynamic"; private static final String KEY_MANIFEST = "manifest"; private static final String KEY_PINNED = "pinned"; private static final String KEY_BITMAPS = "bitmaps"; private static final String KEY_BITMAP_BYTES = "bitmapBytes"; /** * All the shortcuts from the package, keyed on IDs. */ Loading Loading @@ -1198,6 +1206,42 @@ class ShortcutPackage extends ShortcutPackageItem { pw.println(")"); } @Override public JSONObject dumpCheckin(boolean clear) throws JSONException { final JSONObject result = super.dumpCheckin(clear); int numDynamic = 0; int numPinned = 0; int numManifest = 0; int numBitmaps = 0; long totalBitmapSize = 0; final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts; final int size = shortcuts.size(); for (int i = 0; i < size; i++) { final ShortcutInfo si = shortcuts.valueAt(i); if (si.isDynamic()) numDynamic++; if (si.isDeclaredInManifest()) numManifest++; if (si.isPinned()) numPinned++; if (si.getBitmapPath() != null) { numBitmaps++; totalBitmapSize += new File(si.getBitmapPath()).length(); } } result.put(KEY_DYNAMIC, numDynamic); result.put(KEY_MANIFEST, numManifest); result.put(KEY_PINNED, numPinned); result.put(KEY_BITMAPS, numBitmaps); result.put(KEY_BITMAP_BYTES, totalBitmapSize); // TODO Log update frequency too. return result; } @Override public void saveToXml(@NonNull XmlSerializer out, boolean forBackup) throws IOException, XmlPullParserException { Loading services/core/java/com/android/server/pm/ShortcutPackageItem.java +9 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.util.Slog; import com.android.internal.util.Preconditions; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading @@ -31,6 +33,7 @@ import java.io.IOException; */ abstract class ShortcutPackageItem { private static final String TAG = ShortcutService.TAG; private static final String KEY_NAME = "name"; private final int mPackageUserId; private final String mPackageName; Loading Loading @@ -137,6 +140,12 @@ abstract class ShortcutPackageItem { public abstract void saveToXml(@NonNull XmlSerializer out, boolean forBackup) throws IOException, XmlPullParserException; public JSONObject dumpCheckin(boolean clear) throws JSONException { final JSONObject result = new JSONObject(); result.put(KEY_NAME, mPackageName); return result; } /** * Verify various internal states. */ Loading services/core/java/com/android/server/pm/ShortcutService.java +64 −12 Original line number Diff line number Diff line Loading @@ -95,6 +95,9 @@ import com.android.server.pm.ShortcutUser.PackageWithUser; import libcore.io.IoUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading Loading @@ -184,6 +187,10 @@ public class ShortcutService extends IShortcutService.Stub { private static final String LAUNCHER_INTENT_CATEGORY = Intent.CATEGORY_LAUNCHER; private static final String KEY_SHORTCUT = "shortcut"; private static final String KEY_LOW_RAM = "lowRam"; private static final String KEY_ICON_SIZE = "iconSize"; @VisibleForTesting interface ConfigConstants { /** Loading Loading @@ -1352,10 +1359,18 @@ public class ShortcutService extends IShortcutService.Stub { if (isCallerSystem()) { return; } injectEnforceCallingPermission( enforceCallingOrSelfPermission( android.Manifest.permission.RESET_SHORTCUT_MANAGER_THROTTLING, null); } private void enforceCallingOrSelfPermission( @NonNull String permission, @Nullable String message) { if (isCallerSystem()) { return; } injectEnforceCallingPermission(permission, message); } /** * Somehow overriding ServiceContext.enforceCallingPermission() in the unit tests would confuse * mockito. So instead we extracted it here and override it in the tests. Loading Loading @@ -2981,20 +2996,29 @@ public class ShortcutService extends IShortcutService.Stub { @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { pw.println("Permission Denial: can't dump UserManager from from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + " without permission " + android.Manifest.permission.DUMP); return; enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "can't dump by this caller"); boolean checkin = false; boolean clear = false; if (args != null) { for (String arg : args) { if ("-c".equals(arg)) { checkin = true; } else if ("--checkin".equals(arg)) { checkin = true; clear = true; } } dumpInner(pw, args); } @VisibleForTesting void dumpInner(PrintWriter pw, String[] args) { if (checkin) { dumpCheckin(pw, clear); } else { dumpInner(pw); } } private void dumpInner(PrintWriter pw) { synchronized (mLock) { final long now = injectCurrentTimeMillis(); pw.print("Now: ["); Loading Loading @@ -3106,6 +3130,34 @@ public class ShortcutService extends IShortcutService.Stub { (count == 0 ? 0 : ((double) dur) / count))); } /** * Dumpsys for checkin. * * @param clear if true, clear the history information. Some other system services have this * behavior but shortcut service doesn't for now. */ private void dumpCheckin(PrintWriter pw, boolean clear) { synchronized (mLock) { try { final JSONArray users = new JSONArray(); for (int i = 0; i < mUsers.size(); i++) { users.put(mUsers.valueAt(i).dumpCheckin(clear)); } final JSONObject result = new JSONObject(); result.put(KEY_SHORTCUT, users); result.put(KEY_LOW_RAM, injectIsLowRamDevice()); result.put(KEY_ICON_SIZE, mMaxIconDimension); pw.println(result.toString(1)); } catch (JSONException e) { Slog.e(TAG, "Unable to write in json", e); } } } // === Shell support === @Override Loading services/core/java/com/android/server/pm/ShortcutUser.java +30 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ import com.android.internal.util.Preconditions; import libcore.util.Objects; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading @@ -55,6 +58,9 @@ class ShortcutUser { private static final String ATTR_VALUE = "value"; private static final String ATTR_KNOWN_LOCALES = "locales"; private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time"; private static final String KEY_USER_ID = "userId"; private static final String KEY_LAUNCHERS = "launchers"; private static final String KEY_PACKAGES = "packages"; static final class PackageWithUser { final int userId; Loading Loading @@ -503,4 +509,28 @@ class ShortcutUser { pw.print(Formatter.formatFileSize(mService.mContext, size)); pw.println(")"); } public JSONObject dumpCheckin(boolean clear) throws JSONException { final JSONObject result = new JSONObject(); result.put(KEY_USER_ID, mUserId); { final JSONArray launchers = new JSONArray(); for (int i = 0; i < mLaunchers.size(); i++) { launchers.put(mLaunchers.valueAt(i).dumpCheckin(clear)); } result.put(KEY_LAUNCHERS, launchers); } { final JSONArray packages = new JSONArray(); for (int i = 0; i < mPackages.size(); i++) { packages.put(mPackages.valueAt(i).dumpCheckin(clear)); } result.put(KEY_PACKAGES, packages); } return result; } } Loading
services/core/java/com/android/server/pm/ShortcutLauncher.java +11 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.server.pm.ShortcutUser.PackageWithUser; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading Loading @@ -288,6 +290,15 @@ class ShortcutLauncher extends ShortcutPackageItem { } } @Override public JSONObject dumpCheckin(boolean clear) throws JSONException { final JSONObject result = super.dumpCheckin(clear); // Nothing really interesting to dump. return result; } @VisibleForTesting ArraySet<String> getAllPinnedShortcutsForTest(String packageName, int packageUserId) { return new ArraySet<>(mPinnedShortcuts.get(PackageWithUser.of(packageUserId, packageName))); Loading
services/core/java/com/android/server/pm/ShortcutPackage.java +44 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ import com.android.internal.util.XmlUtils; import com.android.server.pm.ShortcutService.ShortcutOperation; import com.android.server.pm.ShortcutService.Stats; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading Loading @@ -93,6 +95,12 @@ class ShortcutPackage extends ShortcutPackageItem { private static final String TAG_STRING_ARRAY_XMLUTILS = "string-array"; private static final String ATTR_NAME_XMLUTILS = "name"; private static final String KEY_DYNAMIC = "dynamic"; private static final String KEY_MANIFEST = "manifest"; private static final String KEY_PINNED = "pinned"; private static final String KEY_BITMAPS = "bitmaps"; private static final String KEY_BITMAP_BYTES = "bitmapBytes"; /** * All the shortcuts from the package, keyed on IDs. */ Loading Loading @@ -1198,6 +1206,42 @@ class ShortcutPackage extends ShortcutPackageItem { pw.println(")"); } @Override public JSONObject dumpCheckin(boolean clear) throws JSONException { final JSONObject result = super.dumpCheckin(clear); int numDynamic = 0; int numPinned = 0; int numManifest = 0; int numBitmaps = 0; long totalBitmapSize = 0; final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts; final int size = shortcuts.size(); for (int i = 0; i < size; i++) { final ShortcutInfo si = shortcuts.valueAt(i); if (si.isDynamic()) numDynamic++; if (si.isDeclaredInManifest()) numManifest++; if (si.isPinned()) numPinned++; if (si.getBitmapPath() != null) { numBitmaps++; totalBitmapSize += new File(si.getBitmapPath()).length(); } } result.put(KEY_DYNAMIC, numDynamic); result.put(KEY_MANIFEST, numManifest); result.put(KEY_PINNED, numPinned); result.put(KEY_BITMAPS, numBitmaps); result.put(KEY_BITMAP_BYTES, totalBitmapSize); // TODO Log update frequency too. return result; } @Override public void saveToXml(@NonNull XmlSerializer out, boolean forBackup) throws IOException, XmlPullParserException { Loading
services/core/java/com/android/server/pm/ShortcutPackageItem.java +9 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.util.Slog; import com.android.internal.util.Preconditions; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading @@ -31,6 +33,7 @@ import java.io.IOException; */ abstract class ShortcutPackageItem { private static final String TAG = ShortcutService.TAG; private static final String KEY_NAME = "name"; private final int mPackageUserId; private final String mPackageName; Loading Loading @@ -137,6 +140,12 @@ abstract class ShortcutPackageItem { public abstract void saveToXml(@NonNull XmlSerializer out, boolean forBackup) throws IOException, XmlPullParserException; public JSONObject dumpCheckin(boolean clear) throws JSONException { final JSONObject result = new JSONObject(); result.put(KEY_NAME, mPackageName); return result; } /** * Verify various internal states. */ Loading
services/core/java/com/android/server/pm/ShortcutService.java +64 −12 Original line number Diff line number Diff line Loading @@ -95,6 +95,9 @@ import com.android.server.pm.ShortcutUser.PackageWithUser; import libcore.io.IoUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading Loading @@ -184,6 +187,10 @@ public class ShortcutService extends IShortcutService.Stub { private static final String LAUNCHER_INTENT_CATEGORY = Intent.CATEGORY_LAUNCHER; private static final String KEY_SHORTCUT = "shortcut"; private static final String KEY_LOW_RAM = "lowRam"; private static final String KEY_ICON_SIZE = "iconSize"; @VisibleForTesting interface ConfigConstants { /** Loading Loading @@ -1352,10 +1359,18 @@ public class ShortcutService extends IShortcutService.Stub { if (isCallerSystem()) { return; } injectEnforceCallingPermission( enforceCallingOrSelfPermission( android.Manifest.permission.RESET_SHORTCUT_MANAGER_THROTTLING, null); } private void enforceCallingOrSelfPermission( @NonNull String permission, @Nullable String message) { if (isCallerSystem()) { return; } injectEnforceCallingPermission(permission, message); } /** * Somehow overriding ServiceContext.enforceCallingPermission() in the unit tests would confuse * mockito. So instead we extracted it here and override it in the tests. Loading Loading @@ -2981,20 +2996,29 @@ public class ShortcutService extends IShortcutService.Stub { @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { pw.println("Permission Denial: can't dump UserManager from from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + " without permission " + android.Manifest.permission.DUMP); return; enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "can't dump by this caller"); boolean checkin = false; boolean clear = false; if (args != null) { for (String arg : args) { if ("-c".equals(arg)) { checkin = true; } else if ("--checkin".equals(arg)) { checkin = true; clear = true; } } dumpInner(pw, args); } @VisibleForTesting void dumpInner(PrintWriter pw, String[] args) { if (checkin) { dumpCheckin(pw, clear); } else { dumpInner(pw); } } private void dumpInner(PrintWriter pw) { synchronized (mLock) { final long now = injectCurrentTimeMillis(); pw.print("Now: ["); Loading Loading @@ -3106,6 +3130,34 @@ public class ShortcutService extends IShortcutService.Stub { (count == 0 ? 0 : ((double) dur) / count))); } /** * Dumpsys for checkin. * * @param clear if true, clear the history information. Some other system services have this * behavior but shortcut service doesn't for now. */ private void dumpCheckin(PrintWriter pw, boolean clear) { synchronized (mLock) { try { final JSONArray users = new JSONArray(); for (int i = 0; i < mUsers.size(); i++) { users.put(mUsers.valueAt(i).dumpCheckin(clear)); } final JSONObject result = new JSONObject(); result.put(KEY_SHORTCUT, users); result.put(KEY_LOW_RAM, injectIsLowRamDevice()); result.put(KEY_ICON_SIZE, mMaxIconDimension); pw.println(result.toString(1)); } catch (JSONException e) { Slog.e(TAG, "Unable to write in json", e); } } } // === Shell support === @Override Loading
services/core/java/com/android/server/pm/ShortcutUser.java +30 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ import com.android.internal.util.Preconditions; import libcore.util.Objects; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading @@ -55,6 +58,9 @@ class ShortcutUser { private static final String ATTR_VALUE = "value"; private static final String ATTR_KNOWN_LOCALES = "locales"; private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time"; private static final String KEY_USER_ID = "userId"; private static final String KEY_LAUNCHERS = "launchers"; private static final String KEY_PACKAGES = "packages"; static final class PackageWithUser { final int userId; Loading Loading @@ -503,4 +509,28 @@ class ShortcutUser { pw.print(Formatter.formatFileSize(mService.mContext, size)); pw.println(")"); } public JSONObject dumpCheckin(boolean clear) throws JSONException { final JSONObject result = new JSONObject(); result.put(KEY_USER_ID, mUserId); { final JSONArray launchers = new JSONArray(); for (int i = 0; i < mLaunchers.size(); i++) { launchers.put(mLaunchers.valueAt(i).dumpCheckin(clear)); } result.put(KEY_LAUNCHERS, launchers); } { final JSONArray packages = new JSONArray(); for (int i = 0; i < mPackages.size(); i++) { packages.put(mPackages.valueAt(i).dumpCheckin(clear)); } result.put(KEY_PACKAGES, packages); } return result; } }