From 43204b8357d781f284037fb8b7b7050ed04a2103 Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Tue, 8 Mar 2016 16:16:44 -0800 Subject: [PATCH] Implement LauncherApps.startShortcut(). Bug 27548047 Change-Id: I357732e22be0959fb573fd6cdaee7c6b439ef7c4 --- api/current.txt | 2 +- api/system-current.txt | 2 +- api/test-current.txt | 2 +- .../android/content/pm/ILauncherApps.aidl | 4 +- .../java/android/content/pm/LauncherApps.java | 11 ++++-- .../content/pm/ShortcutServiceInternal.java | 2 +- .../server/pm/LauncherAppsService.java | 37 ++++++++++++++----- .../android/server/pm/ShortcutService.java | 9 +++-- .../server/pm/ShortcutManagerTest.java | 6 +-- 9 files changed, 49 insertions(+), 26 deletions(-) diff --git a/api/current.txt b/api/current.txt index 22fd25deba4b3..412c877139b3c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9458,7 +9458,7 @@ package android.content.pm { 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 boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle); method public void unregisterCallback(android.content.pm.LauncherApps.Callback); } diff --git a/api/system-current.txt b/api/system-current.txt index 97af1a676695f..141f41709d5ea 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -9792,7 +9792,7 @@ package android.content.pm { 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 boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle); method public void unregisterCallback(android.content.pm.LauncherApps.Callback); } diff --git a/api/test-current.txt b/api/test-current.txt index 9bdd34da4e1f2..f4868a2d14b1f 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -9467,7 +9467,7 @@ package android.content.pm { 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 boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle); method public void unregisterCallback(android.content.pm.LauncherApps.Callback); } diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl index da3c873c043e8..cf3e298fd6d70 100644 --- a/core/java/android/content/pm/ILauncherApps.aidl +++ b/core/java/android/content/pm/ILauncherApps.aidl @@ -50,6 +50,6 @@ interface ILauncherApps { in UserHandle user); void pinShortcuts(String callingPackage, String packageName, in List shortcutIds, in UserHandle user); - void startShortcut(String callingPackage, in ShortcutInfo shortcut, in Rect sourceBounds, - in Bundle startActivityOptions, in UserHandle user); + boolean startShortcut(String callingPackage, String packageName, String id, + in Rect sourceBounds, in Bundle startActivityOptions, in UserHandle user); } diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index f05ecd39a44d2..8e4a0e20097ee 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -496,18 +496,21 @@ public class LauncherApps { * *

Callers mut have the {@link permission#BIND_APPWIDGET} permission. * - * @param shortcut The target shortcut. + * @param packageName The target shortcut package name. + * @param shortcutId The target shortcut ID. * @param sourceBounds The Rect containing the source bounds of the clicked icon. * @param startActivityOptions Options to pass to startActivity. * @param user The UserHandle of the profile. + * @return {@code false} when the shortcut is no longer valid (e.g. the creator application + * has been uninstalled). {@code true} when the shortcut is still valid. */ @RequiresPermission(permission.BIND_APPWIDGET) - public void startShortcut(@NonNull ShortcutInfo shortcut, + public boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId, @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions, @NonNull UserHandle user) { try { - mService.startShortcut(mContext.getPackageName(), shortcut, sourceBounds, - startActivityOptions, user); + return mService.startShortcut(mContext.getPackageName(), packageName, shortcutId, + sourceBounds, startActivityOptions, user); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java index 8055dd92965e6..3d6028a6ffe59 100644 --- a/core/java/android/content/pm/ShortcutServiceInternal.java +++ b/core/java/android/content/pm/ShortcutServiceInternal.java @@ -52,7 +52,7 @@ public abstract class ShortcutServiceInternal { @NonNull List shortcutIds, int userId); public abstract Intent createShortcutIntent(@NonNull String callingPackage, - @NonNull ShortcutInfo shortcut, int userId); + @NonNull String packageName, @NonNull String shortcutId, int userId); public abstract void addListener(@NonNull ShortcutChangeListener listener); } diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 902a3d932bae6..56128708599b3 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -17,6 +17,7 @@ package com.android.server.pm; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppGlobals; import android.content.ComponentName; @@ -328,16 +329,29 @@ public class LauncherAppsService extends SystemService { } @Override - public void startShortcut(String callingPackage, ShortcutInfo shortcut, Rect sourceBounds, - Bundle startActivityOptions, UserHandle user) throws RemoteException { + public boolean startShortcut(String callingPackage, String packageName, String shortcutId, + Rect sourceBounds, Bundle startActivityOptions, UserHandle user) + throws RemoteException { enforceShortcutPermission(user); verifyCallingPackage(callingPackage); final Intent intent = mShortcutServiceInternal.createShortcutIntent(callingPackage, - shortcut, user.getIdentifier()); - // TODO - Slog.e(TAG, "startShortcut() not implemented yet, but the intent is " + intent); - throw new RuntimeException("not implemented yet"); + packageName, shortcutId, user.getIdentifier()); + if (intent == null) { + return false; + } + // Note the target activity doesn't have to be exported. + + intent.setSourceBounds(sourceBounds); + prepareIntentForLaunch(intent, sourceBounds); + + final long ident = Binder.clearCallingIdentity(); + try { + mContext.startActivityAsUser(intent, startActivityOptions, user); + } finally { + Binder.restoreCallingIdentity(ident); + } + return true; } @Override @@ -369,9 +383,7 @@ public class LauncherAppsService extends SystemService { Intent launchIntent = new Intent(Intent.ACTION_MAIN); launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); - launchIntent.setSourceBounds(sourceBounds); - launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + prepareIntentForLaunch(launchIntent, sourceBounds); launchIntent.setPackage(component.getPackageName()); long ident = Binder.clearCallingIdentity(); @@ -408,6 +420,13 @@ public class LauncherAppsService extends SystemService { } } + private void prepareIntentForLaunch(@NonNull Intent launchIntent, + @Nullable Rect sourceBounds) { + launchIntent.setSourceBounds(sourceBounds); + launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + } + @Override public void showAppDetailsAsUser(ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException { diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 5382ff1582824..423767ad87b44 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -1281,14 +1281,15 @@ public class ShortcutService extends IShortcutService.Stub { @Override public Intent createShortcutIntent(@NonNull String callingPackage, - @NonNull ShortcutInfo shortcut, int userId) { + @NonNull String packageName, @NonNull String shortcutId, int userId) { // Calling permission must be checked by LauncherAppsImpl. - Preconditions.checkNotNull(shortcut, "shortcut"); + Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty"); + Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty"); synchronized (mLock) { final ShortcutInfo fullShortcut = - getPackageShortcutsLocked(shortcut.getPackageName(), userId) - .getShortcuts().get(shortcut.getId()); + getPackageShortcutsLocked(packageName, userId) + .getShortcuts().get(shortcutId); if (fullShortcut == null) { return null; } else { diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java index a9b6684a874c6..1f805e9116baa 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java @@ -1101,15 +1101,15 @@ public class ShortcutManagerTest extends AndroidTestCase { setCaller(LAUNCHER_1); Intent intent; intent = mInternal.createShortcutIntent(getCallingPackage(), - s1_1.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO), getCallingUserId()); + CALLING_PACKAGE_1, "s1", getCallingUserId()); assertEquals(ShortcutActivity2.class.getName(), intent.getComponent().getClassName()); intent = mInternal.createShortcutIntent(getCallingPackage(), - s1_2.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO), getCallingUserId()); + CALLING_PACKAGE_1, "s2", getCallingUserId()); assertEquals(ShortcutActivity3.class.getName(), intent.getComponent().getClassName()); intent = mInternal.createShortcutIntent(getCallingPackage(), - s2_1.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO), getCallingUserId()); + CALLING_PACKAGE_2, "s1", getCallingUserId()); assertEquals(ShortcutActivity.class.getName(), intent.getComponent().getClassName()); // TODO Check extra, etc