Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f7362d9 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Introducing ShortcutManager

What's supported:
- Most APIs are implemented, except for SM.updateShortcuts(),
the icon APIs in LA, and LA.startShortcut().
- Persisting information, except for icons
- Throttling

In addition, now PersistableBundle has a public copy
constructor from a Bundle. (Do we want to @hide it?)

TODOs:
- Add icon support
- Implement missing APIs
- Listen to PACKAGE_* broadcasts and do clean-up
- Support multi-launcher apps (pinned shortcuts per launcher)
- Dev option to reset throttling
- Load throttling config from Settings
- Backup & restore
- Figure out LauncherApps permissions (BIND_APPWIDGETS??)
- Other minor TODOs in the code
- Better javadoc

Note: This requires Idf2f9ae816e1f3d822a6286a4cf738c14e29a45e

Bug 27325877

Change-Id: Ia5aa555a4759df5f79a859338f1dc5e624cd0e35
parent b7492623
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ LOCAL_SRC_FILES += \
	core/java/android/content/pm/IPackageMoveObserver.aidl \
	core/java/android/content/pm/IPackageStatsObserver.aidl \
	core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
	core/java/android/content/pm/IShortcutService.aidl \
	core/java/android/database/IContentObserver.aidl \
	../av/camera/aidl/android/hardware/ICameraService.aidl \
	../av/camera/aidl/android/hardware/ICameraServiceListener.aidl \
@@ -650,6 +651,7 @@ aidl_files := \
	frameworks/base/core/java/android/content/pm/ProviderInfo.aidl \
	frameworks/base/core/java/android/content/pm/PackageStats.aidl \
	frameworks/base/core/java/android/content/pm/PermissionGroupInfo.aidl \
	frameworks/base/core/java/android/content/pm/ShortcutInfo.aidl \
	frameworks/base/core/java/android/content/pm/LabeledIntent.aidl \
	frameworks/base/core/java/android/content/ComponentName.aidl \
	frameworks/base/core/java/android/content/SyncStats.aidl \
+70 −0
Original line number Diff line number Diff line
@@ -8138,6 +8138,7 @@ package android.content {
    field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
    field public static final java.lang.String SEARCH_SERVICE = "search";
    field public static final java.lang.String SENSOR_SERVICE = "sensor";
    field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
    field public static final java.lang.String STORAGE_SERVICE = "storage";
    field public static final java.lang.String TELECOM_SERVICE = "telecom";
    field public static final java.lang.String TELEPHONY_SERVICE = "phone";
@@ -9443,13 +9444,19 @@ package android.content.pm {
  public class LauncherApps {
    method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
    method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
    method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
    method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
    method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
    method public void registerCallback(android.content.pm.LauncherApps.Callback);
    method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
    method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
    method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
    method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
    method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
  }
@@ -9462,6 +9469,18 @@ package android.content.pm {
    method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle);
    method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
    method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle);
    method public void onShortcutsChanged(java.lang.String, java.util.List<android.content.pm.ShortcutInfo>, android.os.UserHandle);
  }
  public static class LauncherApps.ShortcutQuery {
    ctor public LauncherApps.ShortcutQuery();
    method public void setActivity(android.content.ComponentName);
    method public void setChangedSince(long);
    method public void setPackage(java.lang.String);
    method public void setQueryFlags(int);
    field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
    field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
    field public static final int FLAG_GET_PINNED = 2; // 0x2
  }
  public class PackageInfo implements android.os.Parcelable {
@@ -9961,6 +9980,56 @@ package android.content.pm {
    field public java.lang.String permission;
  }
  public class ShortcutInfo implements android.os.Parcelable {
    method public int describeContents();
    method public android.content.ComponentName getActivityComponent();
    method public android.os.PersistableBundle getExtras();
    method public java.lang.String getId();
    method public android.content.Intent getIntent();
    method public long getLastChangedTimestamp();
    method public java.lang.String getPackageName();
    method public java.lang.String getTitle();
    method public int getWeight();
    method public boolean hasIconFile();
    method public boolean hasIconResource();
    method public boolean isDynamic();
    method public boolean isPinned();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int CLONE_REMOVE_FOR_CREATOR = 1; // 0x1
    field public static final int CLONE_REMOVE_FOR_LAUNCHER = 3; // 0x3
    field public static final int CLONE_REMOVE_NON_KEY_INFO = 4; // 0x4
    field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
    field public static final int FLAG_DYNAMIC = 1; // 0x1
    field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
    field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
    field public static final int FLAG_PINNED = 2; // 0x2
  }
  public static class ShortcutInfo.Builder {
    ctor public ShortcutInfo.Builder(android.content.Context);
    method public android.content.pm.ShortcutInfo build();
    method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
    method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
    method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
    method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
    method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
    method public android.content.pm.ShortcutInfo.Builder setTitle(java.lang.String);
    method public android.content.pm.ShortcutInfo.Builder setWeight(int);
  }
  public class ShortcutManager {
    method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
    method public void deleteAllDynamicShortcuts();
    method public void deleteDynamicShortcut(java.lang.String);
    method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
    method public int getMaxDynamicShortcutCount();
    method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
    method public long getRateLimitResetTime();
    method public int getRemainingCallCount();
    method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
    method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
  }
  public class Signature implements android.os.Parcelable {
    ctor public Signature(byte[]);
    ctor public Signature(java.lang.String);
@@ -29003,6 +29072,7 @@ package android.os {
    ctor public PersistableBundle();
    ctor public PersistableBundle(int);
    ctor public PersistableBundle(android.os.PersistableBundle);
    ctor public PersistableBundle(android.os.Bundle);
    method public java.lang.Object clone();
    method public int describeContents();
    method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
+70 −0
Original line number Diff line number Diff line
@@ -8444,6 +8444,7 @@ package android.content {
    field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
    field public static final java.lang.String SEARCH_SERVICE = "search";
    field public static final java.lang.String SENSOR_SERVICE = "sensor";
    field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
    field public static final java.lang.String STORAGE_SERVICE = "storage";
    field public static final java.lang.String TELECOM_SERVICE = "telecom";
    field public static final java.lang.String TELEPHONY_SERVICE = "phone";
@@ -9777,13 +9778,19 @@ package android.content.pm {
  public class LauncherApps {
    method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
    method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
    method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
    method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
    method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
    method public void registerCallback(android.content.pm.LauncherApps.Callback);
    method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
    method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
    method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
    method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
    method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
  }
@@ -9796,6 +9803,18 @@ package android.content.pm {
    method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle);
    method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
    method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle);
    method public void onShortcutsChanged(java.lang.String, java.util.List<android.content.pm.ShortcutInfo>, android.os.UserHandle);
  }
  public static class LauncherApps.ShortcutQuery {
    ctor public LauncherApps.ShortcutQuery();
    method public void setActivity(android.content.ComponentName);
    method public void setChangedSince(long);
    method public void setPackage(java.lang.String);
    method public void setQueryFlags(int);
    field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
    field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
    field public static final int FLAG_GET_PINNED = 2; // 0x2
  }
  public class PackageInfo implements android.os.Parcelable {
@@ -10355,6 +10374,56 @@ package android.content.pm {
    field public java.lang.String permission;
  }
  public class ShortcutInfo implements android.os.Parcelable {
    method public int describeContents();
    method public android.content.ComponentName getActivityComponent();
    method public android.os.PersistableBundle getExtras();
    method public java.lang.String getId();
    method public android.content.Intent getIntent();
    method public long getLastChangedTimestamp();
    method public java.lang.String getPackageName();
    method public java.lang.String getTitle();
    method public int getWeight();
    method public boolean hasIconFile();
    method public boolean hasIconResource();
    method public boolean isDynamic();
    method public boolean isPinned();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int CLONE_REMOVE_FOR_CREATOR = 1; // 0x1
    field public static final int CLONE_REMOVE_FOR_LAUNCHER = 3; // 0x3
    field public static final int CLONE_REMOVE_NON_KEY_INFO = 4; // 0x4
    field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
    field public static final int FLAG_DYNAMIC = 1; // 0x1
    field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
    field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
    field public static final int FLAG_PINNED = 2; // 0x2
  }
  public static class ShortcutInfo.Builder {
    ctor public ShortcutInfo.Builder(android.content.Context);
    method public android.content.pm.ShortcutInfo build();
    method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
    method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
    method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
    method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
    method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
    method public android.content.pm.ShortcutInfo.Builder setTitle(java.lang.String);
    method public android.content.pm.ShortcutInfo.Builder setWeight(int);
  }
  public class ShortcutManager {
    method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
    method public void deleteAllDynamicShortcuts();
    method public void deleteDynamicShortcut(java.lang.String);
    method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
    method public int getMaxDynamicShortcutCount();
    method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
    method public long getRateLimitResetTime();
    method public int getRemainingCallCount();
    method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
    method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
  }
  public class Signature implements android.os.Parcelable {
    ctor public Signature(byte[]);
    ctor public Signature(java.lang.String);
@@ -31288,6 +31357,7 @@ package android.os {
    ctor public PersistableBundle();
    ctor public PersistableBundle(int);
    ctor public PersistableBundle(android.os.PersistableBundle);
    ctor public PersistableBundle(android.os.Bundle);
    method public java.lang.Object clone();
    method public int describeContents();
    method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
+70 −0
Original line number Diff line number Diff line
@@ -8144,6 +8144,7 @@ package android.content {
    field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
    field public static final java.lang.String SEARCH_SERVICE = "search";
    field public static final java.lang.String SENSOR_SERVICE = "sensor";
    field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
    field public static final java.lang.String STORAGE_SERVICE = "storage";
    field public static final java.lang.String TELECOM_SERVICE = "telecom";
    field public static final java.lang.String TELEPHONY_SERVICE = "phone";
@@ -9452,13 +9453,19 @@ package android.content.pm {
  public class LauncherApps {
    method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
    method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
    method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
    method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
    method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
    method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
    method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
    method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
    method public void registerCallback(android.content.pm.LauncherApps.Callback);
    method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
    method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
    method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
    method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
    method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
  }
@@ -9471,6 +9478,18 @@ package android.content.pm {
    method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle);
    method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
    method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle);
    method public void onShortcutsChanged(java.lang.String, java.util.List<android.content.pm.ShortcutInfo>, android.os.UserHandle);
  }
  public static class LauncherApps.ShortcutQuery {
    ctor public LauncherApps.ShortcutQuery();
    method public void setActivity(android.content.ComponentName);
    method public void setChangedSince(long);
    method public void setPackage(java.lang.String);
    method public void setQueryFlags(int);
    field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
    field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
    field public static final int FLAG_GET_PINNED = 2; // 0x2
  }
  public class PackageInfo implements android.os.Parcelable {
@@ -9971,6 +9990,56 @@ package android.content.pm {
    field public java.lang.String permission;
  }
  public class ShortcutInfo implements android.os.Parcelable {
    method public int describeContents();
    method public android.content.ComponentName getActivityComponent();
    method public android.os.PersistableBundle getExtras();
    method public java.lang.String getId();
    method public android.content.Intent getIntent();
    method public long getLastChangedTimestamp();
    method public java.lang.String getPackageName();
    method public java.lang.String getTitle();
    method public int getWeight();
    method public boolean hasIconFile();
    method public boolean hasIconResource();
    method public boolean isDynamic();
    method public boolean isPinned();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int CLONE_REMOVE_FOR_CREATOR = 1; // 0x1
    field public static final int CLONE_REMOVE_FOR_LAUNCHER = 3; // 0x3
    field public static final int CLONE_REMOVE_NON_KEY_INFO = 4; // 0x4
    field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
    field public static final int FLAG_DYNAMIC = 1; // 0x1
    field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
    field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
    field public static final int FLAG_PINNED = 2; // 0x2
  }
  public static class ShortcutInfo.Builder {
    ctor public ShortcutInfo.Builder(android.content.Context);
    method public android.content.pm.ShortcutInfo build();
    method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
    method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
    method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
    method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
    method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
    method public android.content.pm.ShortcutInfo.Builder setTitle(java.lang.String);
    method public android.content.pm.ShortcutInfo.Builder setWeight(int);
  }
  public class ShortcutManager {
    method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
    method public void deleteAllDynamicShortcuts();
    method public void deleteDynamicShortcut(java.lang.String);
    method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
    method public int getMaxDynamicShortcutCount();
    method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
    method public long getRateLimitResetTime();
    method public int getRemainingCallCount();
    method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
    method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
  }
  public class Signature implements android.os.Parcelable {
    ctor public Signature(byte[]);
    ctor public Signature(java.lang.String);
@@ -29014,6 +29083,7 @@ package android.os {
    ctor public PersistableBundle();
    ctor public PersistableBundle(int);
    ctor public PersistableBundle(android.os.PersistableBundle);
    ctor public PersistableBundle(android.os.Bundle);
    method public java.lang.Object clone();
    method public int describeContents();
    method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
+11 −0
Original line number Diff line number Diff line
@@ -37,7 +37,9 @@ import android.content.Context;
import android.content.IRestrictionsManager;
import android.content.RestrictionsManager;
import android.content.pm.ILauncherApps;
import android.content.pm.IShortcutService;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutManager;
import android.content.res.Resources;
import android.hardware.ConsumerIrManager;
import android.hardware.ISerialManager;
@@ -748,6 +750,15 @@ final class SystemServiceRegistry {
                Log.i(TAG, "Creating new instance of SoundTriggerManager object.");
                return new SoundTriggerManager(ctx, ISoundTriggerService.Stub.asInterface(b));
            }});

        registerService(Context.SHORTCUT_SERVICE, ShortcutManager.class,
                new CachedServiceFetcher<ShortcutManager>() {
                    @Override
                    public ShortcutManager createService(ContextImpl ctx) {
                        IBinder b = ServiceManager.getService(Context.SHORTCUT_SERVICE);
                        return new ShortcutManager(ctx,
                                IShortcutService.Stub.asInterface(b));
                    }});
    }

    /**
Loading