summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt4
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java31
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java37
-rw-r--r--core/java/android/appwidget/AppWidgetProviderInfo.java5
-rw-r--r--core/java/com/android/internal/appwidget/IAppWidgetService.aidl7
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java136
6 files changed, 64 insertions, 156 deletions
diff --git a/api/current.txt b/api/current.txt
index 8514584..e70be0e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5747,7 +5747,7 @@ package android.appwidget {
method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
method protected void onProvidersChanged();
- method public final void startAppWidgetConfigureActivityForResult(android.app.Activity, android.content.Intent, int);
+ method public final void startAppWidgetConfigureActivityForResult(android.app.Activity, int, int, int, android.os.Bundle);
method public void startListening();
method public void stopListening();
}
@@ -5775,7 +5775,7 @@ package android.appwidget {
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
- method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfiles(android.os.UserHandle[]);
+ method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public void notifyAppWidgetViewDataChanged(int[], int);
method public void notifyAppWidgetViewDataChanged(int, int);
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 66a6eb6..69716e5 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -19,12 +19,15 @@ package android.appwidget;
import java.util.ArrayList;
import java.util.HashMap;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -199,32 +202,30 @@ public class AppWidgetHost {
/**
* Starts an app widget provider configure activity for result on behalf of the caller.
* Use this method if the provider is in another profile as you are not allowed to start
- * an activity in another profile. The provided intent must have action {@link
- * AppWidgetManager#ACTION_APPWIDGET_CONFIGURE}. The widget id must be specified by
- * the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} extra. The provider configure
- * activity must be specified as the component name of the intent via {@link
- * Intent#setComponent(android.content.ComponentName)}. The user profile under which
- * the provider operates is specified via the {@link
- * AppWidgetManager#EXTRA_APPWIDGET_PROVIDER_PROFILE} extra. If a user profile is
- * not provided, the current user is used. Finally, you can optionally provide a
- * request code that is returned in {@link Activity#onActivityResult(int, int,
- * android.content.Intent)}.
+ * an activity in another profile. You can optionally provide a request code that is
+ * returned in {@link Activity#onActivityResult(int, int, android.content.Intent)} and
+ * an options bundle to be passed to the started activity.
+ * <p>
+ * Note that the provided app widget has to be bound for this method to work.
+ * </p>
*
* @param activity The activity from which to start the configure one.
- * @param intent Properly populated intent for launching the configuration activity.
+ * @param appWidgetId The bound app widget whose provider's config activity to start.
* @param requestCode Optional request code retuned with the result.
+ * @param intentFlags Optional intent flags.
*
* @throws android.content.ActivityNotFoundException If the activity is not found.
*
* @see AppWidgetProviderInfo#getProfile()
*/
- public final void startAppWidgetConfigureActivityForResult(Activity activity, Intent intent,
- int requestCode) {
+ public final void startAppWidgetConfigureActivityForResult(@NonNull Activity activity,
+ int appWidgetId, int intentFlags, int requestCode, @Nullable Bundle options) {
try {
IntentSender intentSender = sService.createAppWidgetConfigIntentSender(
- mContext.getPackageName(), intent);
+ mContext.getPackageName(), appWidgetId, intentFlags);
if (intentSender != null) {
- activity.startIntentSenderForResult(intentSender, requestCode, null, 0, 0, 0);
+ activity.startIntentSenderForResult(intentSender, requestCode, null, 0, 0, 0,
+ options);
} else {
throw new ActivityNotFoundException();
}
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index e5d1d95..086eb7d 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -16,6 +16,7 @@
package android.appwidget;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -673,24 +674,24 @@ public class AppWidgetManager {
}
/**
- * Gets the AppWidget providers for the given user profiles. User profiles can only
+ * Gets the AppWidget providers for the given user profile. User profile can only
* be the current user or a profile of the current user. For example, the current
* user may have a corporate profile. In this case the parent user profile has a
* child profile, the corporate one.
*
- * @param profiles The profiles for which to get providers. Passing null is equivaled
+ * @param profile The profile for which to get providers. Passing null is equivaled
* to passing only the current user handle.
* @return The intalled providers.
*
* @see android.os.Process#myUserHandle()
* @see android.os.UserManager#getUserProfiles()
*/
- public List<AppWidgetProviderInfo> getInstalledProvidersForProfiles(UserHandle[] profiles) {
+ public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(@Nullable UserHandle profile) {
if (mService == null) {
return Collections.emptyList();
}
- return getInstalledProvidersForProfiles(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
- profiles);
+ return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
+ profile);
}
/**
@@ -700,7 +701,7 @@ public class AppWidgetManager {
if (mService == null) {
return Collections.emptyList();
}
- return getInstalledProvidersForProfiles(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
+ return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
null);
}
@@ -720,18 +721,18 @@ public class AppWidgetManager {
if (mService == null) {
return Collections.emptyList();
}
- return getInstalledProvidersForProfiles(categoryFilter, null);
+ return getInstalledProvidersForProfile(categoryFilter, null);
}
/**
- * Gets the AppWidget providers for the given user profiles. User profiles can only
+ * Gets the AppWidget providers for the given user profile. User profile can only
* be the current user or a profile of the current user. For example, the current
* user may have a corporate profile. In this case the parent user profile has a
* child profile, the corporate one.
*
* @param categoryFilter Will only return providers which register as any of the specified
* specified categories. See {@link AppWidgetProviderInfo#widgetCategory}.
- * @param profiles Child profiles of the current user which to be queried. The user
+ * @param profile A profile of the current user which to be queried. The user
* is itself also a profile. If null, the providers only for the current user
* are returned.
* @return The intalled providers.
@@ -741,25 +742,19 @@ public class AppWidgetManager {
*
* @hide
*/
- public List<AppWidgetProviderInfo> getInstalledProvidersForProfiles(int categoryFilter,
- UserHandle[] profiles) {
+ public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
+ UserHandle profile) {
if (mService == null) {
return Collections.emptyList();
}
- int[] profileIds = null;
-
- if (profiles != null) {
- final int profileCount = profiles.length;
- profileIds = new int[profileCount];
- for (int i = 0; i < profileCount; i++) {
- profileIds[i] = profiles[i].getIdentifier();
- }
+ if (profile == null) {
+ profile = Process.myUserHandle();
}
try {
- List<AppWidgetProviderInfo> providers = mService.getInstalledProviders(categoryFilter,
- profileIds);
+ List<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
+ categoryFilter, profile.getIdentifier());
if (providers == null) {
return Collections.emptyList();
}
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 6835368..a767246 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -16,6 +16,7 @@
package android.appwidget;
+import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -269,7 +270,7 @@ public class AppWidgetProviderInfo implements Parcelable {
* {@link android.util.DisplayMetrics#densityDpi}.
* @return The provider icon.
*/
- public final Drawable loadIcon(Context context, int density) {
+ public final Drawable loadIcon(@NonNull Context context, int density) {
return loadDrawable(context, density, providerInfo.getIconResource());
}
@@ -289,7 +290,7 @@ public class AppWidgetProviderInfo implements Parcelable {
* {@link android.util.DisplayMetrics#densityDpi}.
* @return The widget preview image.
*/
- public final Drawable loadPreviewImage(Context context, int density) {
+ public final Drawable loadPreviewImage(@NonNull Context context, int density) {
return loadDrawable(context, density, previewImage);
}
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 9da1c9d..008d38b 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -41,7 +41,8 @@ interface IAppWidgetService {
void deleteAllHosts();
RemoteViews getAppWidgetViews(String callingPackage, int appWidgetId);
int[] getAppWidgetIdsForHost(String callingPackage, int hostId);
- IntentSender createAppWidgetConfigIntentSender(String callingPackage, in Intent intent);
+ IntentSender createAppWidgetConfigIntentSender(String callingPackage, int appWidgetId,
+ int intentFlags);
//
// for AppWidgetManager
@@ -53,8 +54,8 @@ interface IAppWidgetService {
in RemoteViews views);
void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
void notifyAppWidgetViewDataChanged(String packageName, in int[] appWidgetIds, int viewId);
- List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter,
- in int[] profileIds);
+ List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
+ int profileId);
AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId);
boolean hasBindAppWidgetPermission(in String packageName, int userId);
void setBindAppWidgetPermission(in String packageName, int userId, in boolean permission);
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 4315e0d..609ffda 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -121,8 +121,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private static final int LOADED_PROFILE_ID = -1;
- private static final int DISABLED_PROFILE = -1;
-
private static final int UNKNOWN_USER_ID = -10;
// Bump if the stored widgets need to be upgraded.
@@ -660,7 +658,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
@Override
- public IntentSender createAppWidgetConfigIntentSender(String callingPackage, Intent intent) {
+ public IntentSender createAppWidgetConfigIntentSender(String callingPackage, int appWidgetId,
+ int intentFlags) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
@@ -670,57 +669,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// Make sure the package runs under the caller uid.
mSecurityPolicy.enforceCallFromPackage(callingPackage);
- // The only allowed action is the one to start the configure activity.
- if (!AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) {
- throw new IllegalArgumentException("Only allowed action is "
- + AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
- }
-
- // Verify that widget id is provided.
- final int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
- AppWidgetManager.INVALID_APPWIDGET_ID);
- if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
- throw new IllegalArgumentException("Widget id required");
- }
-
- // Make sure a component name is provided.
- ComponentName component = intent.getComponent();
- if (component == null) {
- throw new IllegalArgumentException("Component name required");
- }
-
- // Verify the user handle.
- UserHandle userHandle = intent.getParcelableExtra(
- AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE);
- if (userHandle != null) {
- // Remove the profile extra as the receiver already runs under this
- // user and this information is of no use to this receiver.
- intent.removeExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE);
-
- // If the user handle is not the caller, check if it is an enabled
- // profile for which the package is white-listed.
- final int profileId = userHandle.getIdentifier();
- if (profileId != userId) {
- // Make sure the passed user handle is a profile in the group.
- final int[] profileIds = mSecurityPolicy.resolveCallerEnabledGroupProfiles(
- new int[]{profileId});
- if (profileIds.length <= 0) {
- // The profile is not in the group or not enabled, done.
- return null;
- }
-
- // Make sure the provider is white-listed.
- if (!mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
- component.getPackageName(), profileId)) {
- throw new IllegalArgumentException("Cannot access provider "
- + component + " in user " + profileIds);
- }
- }
- } else {
- // If a profile is not specified use the caller user id.
- userHandle = new UserHandle(userId);
- }
-
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
@@ -738,19 +686,18 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
throw new IllegalArgumentException("Widget not bound " + appWidgetId);
}
- // Make sure the component refers to the provider config activity.
- if (!component.equals(provider.info.configure)
- || !provider.info.getProfile().equals(userHandle)) {
- throw new IllegalArgumentException("No component" + component
- + " for user " + userHandle.getIdentifier());
- }
+ Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+ intent.setComponent(provider.info.configure);
+ intent.setFlags(intentFlags);
// All right, create the sender.
final long identity = Binder.clearCallingIdentity();
try {
return PendingIntent.getActivityAsUser(
mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
- | PendingIntent.FLAG_CANCEL_CURRENT, null, userHandle)
+ | PendingIntent.FLAG_CANCEL_CURRENT, null,
+ new UserHandle(provider.getUserId()))
.getIntentSender();
} finally {
Binder.restoreCallingIdentity(identity);
@@ -771,9 +718,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
mSecurityPolicy.enforceCallFromPackage(callingPackage);
// Check that if a cross-profile binding is attempted, it is allowed.
- final int[] profileIds = mSecurityPolicy.resolveCallerEnabledGroupProfiles(
- new int[] {providerProfileId});
- if (profileIds.length <= 0) {
+ if (!mSecurityPolicy.isEnabledGroupProfile(providerProfileId)) {
return false;
}
@@ -1309,28 +1254,23 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
@Override
- public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter, int[] profileIds) {
+ public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
+ int profileId) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "getInstalledProvidersForProfiles() " + userId);
}
- if (profileIds != null && profileIds.length > 0) {
- // Make sure the profile ids are children of the calling user.
- profileIds = mSecurityPolicy.resolveCallerEnabledGroupProfiles(profileIds);
- } else {
- profileIds = new int[] {userId};
- }
-
- if (profileIds.length == 0) {
+ // Ensure the profile is in the group and enabled.
+ if (!mSecurityPolicy.isEnabledGroupProfile(profileId)) {
return null;
}
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
- ArrayList<AppWidgetProviderInfo> result = new ArrayList<>();
+ ArrayList<AppWidgetProviderInfo> result = null;
final int providerCount = mProviders.size();
for (int i = 0; i < providerCount; i++) {
@@ -1342,19 +1282,15 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
continue;
}
- // Add providers only for the requested profiles ...
+ // Add providers only for the requested profile that are white-listed.
final int providerProfileId = info.getProfile().getIdentifier();
- final int profileCount = profileIds.length;
- for (int j = 0; j < profileCount; j++) {
- final int profileId = profileIds[j];
- if (providerProfileId == profileId) {
- // ... that are white-listed by the profile manager.
- if (mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
- provider.id.componentName.getPackageName(), providerProfileId)) {
- result.add(cloneIfLocalBinder(info));
- }
- break;
+ if (providerProfileId == profileId
+ && mSecurityPolicy.isProviderInCallerOrInProfileAndWhitelListed(
+ provider.id.componentName.getPackageName(), providerProfileId)) {
+ if (result == null) {
+ result = new ArrayList<>();
}
+ result.add(cloneIfLocalBinder(info));
}
}
@@ -2967,35 +2903,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private final class SecurityPolicy {
- public int[] resolveCallerEnabledGroupProfiles(int[] profileIds) {
+ public boolean isEnabledGroupProfile(int profileId) {
final int parentId = UserHandle.getCallingUserId();
-
- int enabledProfileCount = 0;
- final int profileCount = profileIds.length;
- for (int i = 0; i < profileCount; i++) {
- final int profileId = profileIds[i];
- if (!isParentOrProfile(parentId, profileId)) {
- throw new SecurityException("Not the current user or"
- + " a child profile: " + profileId);
- }
- if (!isProfileEnabled(profileId)) {
- profileIds[i] = DISABLED_PROFILE;
- } else {
- enabledProfileCount++;
- }
- }
-
- int resolvedProfileIndex = 0;
- final int[] resolvedProfiles = new int[enabledProfileCount];
- for (int i = 0; i < profileCount; i++) {
- final int profileId = profileIds[i];
- if (profileId != DISABLED_PROFILE) {
- resolvedProfiles[resolvedProfileIndex] = profileId;
- resolvedProfileIndex++;
- }
- }
-
- return resolvedProfiles;
+ return isParentOrProfile(parentId, profileId) && isProfileEnabled(profileId);
}
public int[] getEnabledGroupProfileIds(int userId) {