method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
+ method public boolean isRequestPinAppWidgetSupported();
method public void notifyAppWidgetViewDataChanged(int[], int);
method public void notifyAppWidgetViewDataChanged(int, int);
method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
- field public static final java.lang.String ACTION_CONFIRM_PIN_ITEM = "android.content.pm.action.CONFIRM_PIN_ITEM";
+ field public static final java.lang.String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
+ field public static final java.lang.String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
field public static final java.lang.String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
}
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
+ method public boolean isRequestPinAppWidgetSupported();
method public void notifyAppWidgetViewDataChanged(int[], int);
method public void notifyAppWidgetViewDataChanged(int, int);
method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
- field public static final java.lang.String ACTION_CONFIRM_PIN_ITEM = "android.content.pm.action.CONFIRM_PIN_ITEM";
+ field public static final java.lang.String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
+ field public static final java.lang.String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
field public static final java.lang.String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
}
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
+ method public boolean isRequestPinAppWidgetSupported();
method public void notifyAppWidgetViewDataChanged(int[], int);
method public void notifyAppWidgetViewDataChanged(int, int);
method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
- field public static final java.lang.String ACTION_CONFIRM_PIN_ITEM = "android.content.pm.action.CONFIRM_PIN_ITEM";
+ field public static final java.lang.String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
+ field public static final java.lang.String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
field public static final java.lang.String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
}
}
/**
+ * Return {@code TRUE} if the default launcher supports
+ * {@link #requestPinAppWidget(ComponentName, PendingIntent)}
+ */
+ public boolean isRequestPinAppWidgetSupported() {
+ try {
+ return mService.isRequestPinAppWidgetSupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Request to pin an app widget on the current launcher. It's up to the launcher to accept this
* request (optionally showing a user confirmation). If the request is accepted, the caller will
* get a confirmation with extra {@link #EXTRA_APPWIDGET_ID}.
*
* @see android.content.pm.ShortcutManager#isRequestPinShortcutSupported()
* @see android.content.pm.ShortcutManager#requestPinShortcut(ShortcutInfo, IntentSender)
+ * @see #isRequestPinAppWidgetSupported()
*
* @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
* service or when the user is locked.
void applyRestore(in byte[] payload, int user);
- boolean isRequestPinShortcutSupported(int user);
+ boolean isRequestPinItemSupported(int user, int requestType);
}
\ No newline at end of file
* @see #EXTRA_PIN_ITEM_REQUEST
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_CONFIRM_PIN_ITEM =
- "android.content.pm.action.CONFIRM_PIN_ITEM";
+ public static final String ACTION_CONFIRM_PIN_SHORTCUT =
+ "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
/**
- * An extra for {@link #ACTION_CONFIRM_PIN_ITEM} containing a
- * {@link ShortcutInfo} of the shortcut the publisher app asked to pin.
+ * Activity Action: For the default launcher to show the confirmation dialog to create
+ * a pinned app widget.
+ *
+ * <p>See the {@link android.appwidget.AppWidgetManager#requestPinAppWidget} javadoc for
+ * details.
+ *
+ * <p>
+ * Use {@link #getPinItemRequest(Intent)} to get a {@link PinItemRequest} object,
+ * and call {@link PinItemRequest#accept(Bundle)}
+ * if the user accepts. If the user doesn't accept, no further action is required.
+ *
+ * @see #EXTRA_PIN_ITEM_REQUEST
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_CONFIRM_PIN_APPWIDGET =
+ "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
+
+ /**
+ * An extra for {@link #ACTION_CONFIRM_PIN_SHORTCUT} & {@link #ACTION_CONFIRM_PIN_APPWIDGET}
+ * containing a {@link PinItemRequest} of appropriate type asked to pin.
*
* <p>A helper function {@link #getPinItemRequest(Intent)} can be used
* instead of using this constant directly.
*
- * @see #ACTION_CONFIRM_PIN_ITEM
+ * @see #ACTION_CONFIRM_PIN_SHORTCUT
+ * @see #ACTION_CONFIRM_PIN_APPWIDGET
*/
public static final String EXTRA_PIN_ITEM_REQUEST =
"android.content.pm.extra.PIN_ITEM_REQUEST";
-
private Context mContext;
private ILauncherApps mService;
private PackageManager mPm;
}
/**
- * Represents a "pin shortcut" request made by an app, which is sent with
- * an {@link #ACTION_CONFIRM_PIN_ITEM} intent to the default launcher app.
+ * Represents a "pin shortcut" or a "pin appwidget" request made by an app, which is sent with
+ * an {@link #ACTION_CONFIRM_PIN_SHORTCUT} or {@link #ACTION_CONFIRM_PIN_APPWIDGET} intent
+ * respectively to the default launcher app.
*
* <p>Note the launcher may receive a request to pin a shortcut that is already pinned, because
* the user may actually want to have multiple icons of the same shortcut on the launcher.
* even if the launcher does not call it, the shortcut is already pinned. Also in this case,
* the {@code options} argument to {@link #accept(Bundle)} will be ignored.
*
+ * <p>For AppWidget pin requests launcher should send back the appwidget id as an extra for
+ * {@link #accept(Bundle)} as {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}.
+ *
* @see #EXTRA_PIN_ITEM_REQUEST
* @see #getPinItemRequest(Intent)
*/
*/
public boolean isRequestPinShortcutSupported() {
try {
- return mService.isRequestPinShortcutSupported(injectMyUserId());
+ return mService.isRequestPinItemSupported(injectMyUserId(),
+ LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
public abstract boolean requestPinAppWidget(@NonNull String callingPackage,
@NonNull AppWidgetProviderInfo appWidget, @Nullable IntentSender resultIntent,
int userId);
+
+ public abstract boolean isRequestPinItemSupported(int callingUserId, int requestType);
}
boolean isBoundWidgetPackage(String packageName, int userId);
boolean requestPinAppWidget(String packageName, in ComponentName providerComponent,
in IntentSender resultIntent);
+ boolean isRequestPinAppWidgetSupported();
}
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.content.pm.LauncherApps;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
}
@Override
+ public boolean isRequestPinAppWidgetSupported() {
+ return LocalServices.getService(ShortcutServiceInternal.class)
+ .isRequestPinItemSupported(UserHandle.getCallingUserId(),
+ LauncherApps.PinItemRequest.REQUEST_TYPE_APPWIDGET);
+ }
+
+ @Override
public boolean requestPinAppWidget(String callingPackage, ComponentName componentName,
IntentSender resultSender) {
final int callingUid = Binder.getCallingUid();
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.PinItemRequest;
import android.content.pm.ShortcutInfo;
-import android.os.Binder;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
mLock = lock;
}
- public boolean isRequestPinnedShortcutSupported(int callingUserId) {
- return getRequestPinShortcutConfirmationActivity(callingUserId) != null;
+ public boolean isRequestPinItemSupported(int callingUserId, int requestType) {
+ return getRequestPinConfirmationActivity(callingUserId, requestType) != null;
}
/**
// First, make sure the launcher supports it.
// Find the confirmation activity in the default launcher.
+ final int requestType = inShortcut != null ?
+ PinItemRequest.REQUEST_TYPE_SHORTCUT : PinItemRequest.REQUEST_TYPE_APPWIDGET;
final Pair<ComponentName, Integer> confirmActivity =
- getRequestPinShortcutConfirmationActivity(userId);
+ getRequestPinConfirmationActivity(userId, requestType);
// If the launcher doesn't support it, just return a rejected result and finish.
if (confirmActivity == null) {
request = new PinItemRequest(inAppWidget,
new PinItemRequestInner(this, resultIntent, launcherUid));
}
- return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request);
+ return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request,
+ requestType);
}
/**
}
private boolean startRequestConfirmActivity(ComponentName activity, int launcherUserId,
- PinItemRequest request) {
+ PinItemRequest request, int requestType) {
+ final String action = requestType == LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT ?
+ LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT :
+ LauncherApps.ACTION_CONFIRM_PIN_APPWIDGET;
+
// Start the activity.
- final Intent confirmIntent = new Intent(LauncherApps.ACTION_CONFIRM_PIN_ITEM);
+ final Intent confirmIntent = new Intent(action);
confirmIntent.setComponent(activity);
confirmIntent.putExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST, request);
confirmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
/**
- * Find the activity that handles {@link LauncherApps#ACTION_CONFIRM_PIN_ITEM} in the
+ * Find the activity that handles {@link LauncherApps#ACTION_CONFIRM_PIN_SHORTCUT} in the
* default launcher.
*/
@Nullable
@VisibleForTesting
- Pair<ComponentName, Integer> getRequestPinShortcutConfirmationActivity(
- int callingUserId) {
+ Pair<ComponentName, Integer> getRequestPinConfirmationActivity(
+ int callingUserId, int requestType) {
// Find the default launcher.
final int launcherUserId = mService.getParentOrSelfUserId(callingUserId);
final ComponentName defaultLauncher = mService.getDefaultLauncher(launcherUserId);
return null;
}
final ComponentName activity = mService.injectGetPinConfirmationActivity(
- defaultLauncher.getPackageName(), launcherUserId);
+ defaultLauncher.getPackageName(), launcherUserId, requestType);
return (activity == null) ? null : Pair.create(activity, launcherUserId);
}
}
@Override
- public boolean isRequestPinShortcutSupported(int callingUserId) {
+ public boolean isRequestPinItemSupported(int callingUserId, int requestType) {
final long token = injectClearCallingIdentity();
try {
- return mShortcutRequestPinProcessor.isRequestPinnedShortcutSupported(callingUserId);
+ return mShortcutRequestPinProcessor
+ .isRequestPinItemSupported(callingUserId, requestType);
} finally {
injectRestoreCallingIdentity(token);
}
Preconditions.checkNotNull(appWidget);
return requestPinItem(callingPackage, userId, null, appWidget, resultIntent);
}
+
+ @Override
+ public boolean isRequestPinItemSupported(int callingUserId, int requestType) {
+ return ShortcutService.this.isRequestPinItemSupported(callingUserId, requestType);
+ }
}
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
}
/**
- * Get the {@link LauncherApps#ACTION_CONFIRM_PIN_ITEM} activity in a given package.
+ * Get the {@link LauncherApps#ACTION_CONFIRM_PIN_SHORTCUT} or
+ * {@link LauncherApps#ACTION_CONFIRM_PIN_APPWIDGET} activity in a given package depending on
+ * the requestType.
*/
@Nullable
ComponentName injectGetPinConfirmationActivity(@NonNull String launcherPackageName,
- int launcherUserId) {
+ int launcherUserId, int requestType) {
Preconditions.checkNotNull(launcherPackageName);
+ String action = requestType == LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT ?
+ LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT :
+ LauncherApps.ACTION_CONFIRM_PIN_APPWIDGET;
- final Intent confirmIntent = new Intent(LauncherApps.ACTION_CONFIRM_PIN_ITEM);
- confirmIntent.setPackage(launcherPackageName);
-
+ final Intent confirmIntent = new Intent(action).setPackage(launcherPackageName);
final List<ResolveInfo> candidates = queryActivities(
confirmIntent, launcherUserId, /* exportedOnly =*/ false);
for (ResolveInfo ri : candidates) {
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
+import android.content.pm.LauncherApps;
import android.content.pm.ShortcutServiceInternal;
import android.os.Handler;
import android.os.UserHandle;
assertEquals(provider, providerCaptor.getValue().provider);
}
+ public void testIsRequestPinAppWidgetSupported() {
+ ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class);
+ // Set up users.
+ when(mMockShortcutService.isRequestPinItemSupported(anyInt(), anyInt()))
+ .thenReturn(true, false);
+ assertTrue(mManager.isRequestPinAppWidgetSupported());
+ assertFalse(mManager.isRequestPinAppWidgetSupported());
+
+ verify(mMockShortcutService, times(2)).isRequestPinItemSupported(anyInt(),
+ eq(LauncherApps.PinItemRequest.REQUEST_TYPE_APPWIDGET));
+ }
+
public void testProviderUpdatesReceived() throws Exception {
int widgetId = setupHostAndWidget();
RemoteViews view = new RemoteViews(mPkgName, android.R.layout.simple_list_item_1);
@Override
ComponentName injectGetPinConfirmationActivity(@NonNull String launcherPackageName,
- int launcherUserId) {
+ int launcherUserId, int requestType) {
return mPinConfirmActivityFetcher.apply(launcherPackageName, launcherUserId);
}
Pair<ComponentName, Integer> actual;
// User 0
- actual = mProcessor.getRequestPinShortcutConfirmationActivity(USER_0);
+ actual = mProcessor.getRequestPinConfirmationActivity(USER_0,
+ PinItemRequest.REQUEST_TYPE_SHORTCUT);
assertEquals(LAUNCHER_1, actual.first.getPackageName());
assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
assertEquals(USER_0, (int) actual.second);
// User 10
- actual = mProcessor.getRequestPinShortcutConfirmationActivity(USER_10);
+ actual = mProcessor.getRequestPinConfirmationActivity(USER_10,
+ PinItemRequest.REQUEST_TYPE_SHORTCUT);
assertEquals(LAUNCHER_2, actual.first.getPackageName());
assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
assertEquals(USER_10, (int) actual.second);
// User P0 -> managed profile, return user-0's launcher.
- actual = mProcessor.getRequestPinShortcutConfirmationActivity(USER_P0);
+ actual = mProcessor.getRequestPinConfirmationActivity(USER_P0,
+ PinItemRequest.REQUEST_TYPE_SHORTCUT);
assertEquals(LAUNCHER_1, actual.first.getPackageName());
assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
? null : new ComponentName(packageName, PIN_CONFIRM_ACTIVITY_CLASS);
// User 10 -- still has confirm activity.
- actual = mProcessor.getRequestPinShortcutConfirmationActivity(USER_10);
+ actual = mProcessor.getRequestPinConfirmationActivity(USER_10,
+ PinItemRequest.REQUEST_TYPE_SHORTCUT);
assertEquals(LAUNCHER_2, actual.first.getPackageName());
assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
assertEquals(USER_10, (int) actual.second);
// But user-0 and user p0 no longer has a confirmation activity.
- assertNull(mProcessor.getRequestPinShortcutConfirmationActivity(USER_0));
- assertNull(mProcessor.getRequestPinShortcutConfirmationActivity(USER_P0));
+ assertNull(mProcessor.getRequestPinConfirmationActivity(USER_0,
+ PinItemRequest.REQUEST_TYPE_SHORTCUT));
+ assertNull(mProcessor.getRequestPinConfirmationActivity(USER_P0,
+ PinItemRequest.REQUEST_TYPE_SHORTCUT));
// Check from the public API.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
}
private void assertPinItemRequestIntent(Intent actualIntent, String expectedPackage) {
- assertEquals(LauncherApps.ACTION_CONFIRM_PIN_ITEM, actualIntent.getAction());
+ assertEquals(LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT, actualIntent.getAction());
assertEquals(expectedPackage, actualIntent.getComponent().getPackageName());
assertEquals(PIN_CONFIRM_ACTIVITY_CLASS,
actualIntent.getComponent().getClassName());
}
private void assertPinItemRequestIntent(Intent actualIntent, String expectedPackage) {
- assertEquals(LauncherApps.ACTION_CONFIRM_PIN_ITEM, actualIntent.getAction());
+ assertEquals(LauncherApps.ACTION_CONFIRM_PIN_APPWIDGET, actualIntent.getAction());
assertEquals(expectedPackage, actualIntent.getComponent().getPackageName());
assertEquals(PIN_CONFIRM_ACTIVITY_CLASS,
actualIntent.getComponent().getClassName());