diff options
5 files changed, 54 insertions, 6 deletions
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 6b1c3e2..1f7d1ba 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -48,8 +48,8 @@ public class AppWidgetManager { static final String TAG = "AppWidgetManager"; /** - * Send this from your {@link AppWidgetHost} activity when you want to pick an AppWidget to display. - * The AppWidget picker activity will be launched. + * Activity action to launch from your {@link AppWidgetHost} activity when you want to + * pick an AppWidget to display. The AppWidget picker activity will be launched. * <p> * You must supply the following extras: * <table> @@ -88,8 +88,8 @@ public class AppWidgetManager { ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK"; /** - * Send this from your {@link AppWidgetHost} activity when you want to bind an AppWidget to - * display and bindAppWidgetIdIfAllowed returns false. + * Activity action to launch from your {@link AppWidgetHost} activity when you want to bind + * an AppWidget to display and bindAppWidgetIdIfAllowed returns false. * <p> * You must supply the following extras: * <table> @@ -268,6 +268,9 @@ public class AppWidgetManager { /** * Sent when the custom extras for an AppWidget change. * + * <p class="note">This is a protected intent that can only be sent + * by the system. + * * @see AppWidgetProvider#onAppWidgetOptionsChanged * AppWidgetProvider.onAppWidgetOptionsChanged(Context context, * AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras) @@ -284,6 +287,9 @@ public class AppWidgetManager { /** * Sent when an instance of an AppWidget is removed from the last host. * + * <p class="note">This is a protected intent that can only be sent + * by the system. + * * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context) */ public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED"; @@ -293,6 +299,9 @@ public class AppWidgetManager { * This broadcast is sent at boot time if there is a AppWidgetHost installed with * an instance for this provider. * + * <p class="note">This is a protected intent that can only be sent + * by the system. + * * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context) */ public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED"; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1da99ad..7485962 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -75,6 +75,11 @@ <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" /> <protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" /> + <protected-broadcast android:name="android.appwidget.action.APPWIDGET_UPDATE_OPTIONS" /> + <protected-broadcast android:name="android.appwidget.action.APPWIDGET_DELETED" /> + <protected-broadcast android:name="android.appwidget.action.APPWIDGET_DISABLED" /> + <protected-broadcast android:name="android.appwidget.action.APPWIDGET_ENABLED" /> + <protected-broadcast android:name="android.backup.intent.RUN" /> <protected-broadcast android:name="android.backup.intent.CLEAR" /> <protected-broadcast android:name="android.backup.intent.INIT" /> diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 4c83116..dc4661f 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -19,6 +19,7 @@ package com.android.server.am; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import android.appwidget.AppWidgetManager; import com.android.internal.R; import com.android.internal.app.ThemeUtils; import com.android.internal.os.BatteryStatsImpl; @@ -11737,6 +11738,32 @@ public final class ActivityManagerService extends ActivityManagerNative + callingPid + ", uid=" + callingUid; Slog.w(TAG, msg); throw new SecurityException(msg); + } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) { + // Special case for compatibility: we don't want apps to send this, + // but historically it has not been protected and apps may be using it + // to poke their own app widget. So, instead of making it protected, + // just limit it to the caller. + if (callerApp == null) { + String msg = "Permission Denial: not allowed to send broadcast " + + intent.getAction() + " from unknown caller."; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } else if (intent.getComponent() != null) { + // They are good enough to send to an explicit component... verify + // it is being sent to the calling app. + if (!intent.getComponent().getPackageName().equals( + callerApp.info.packageName)) { + String msg = "Permission Denial: not allowed to send broadcast " + + intent.getAction() + " to " + + intent.getComponent().getPackageName() + " from " + + callerApp.info.packageName; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + } else { + // Limit broadcast to their own package. + intent.setPackage(callerApp.info.packageName); + } } } catch (RemoteException e) { Slog.w(TAG, "Remote exception", e); diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java index fc4ecda..468fd17 100644 --- a/services/java/com/android/server/am/BroadcastQueue.java +++ b/services/java/com/android/server/am/BroadcastQueue.java @@ -29,7 +29,6 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -1071,6 +1070,9 @@ public class BroadcastQueue { pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r); pw.print(" "); pw.println(r.intent.toShortString(false, true, true, false)); + if (r.targetComp != null && r.targetComp != r.intent.getComponent()) { + pw.print(" targetComp: "); pw.println(r.targetComp.toShortString()); + } Bundle bundle = r.intent.getExtras(); if (bundle != null) { pw.print(" extras: "); pw.println(bundle.toString()); diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java index 1cf5b9c..ce14074 100644 --- a/services/java/com/android/server/am/BroadcastRecord.java +++ b/services/java/com/android/server/am/BroadcastRecord.java @@ -37,6 +37,7 @@ import java.util.List; */ class BroadcastRecord extends Binder { final Intent intent; // the original intent that generated us + final ComponentName targetComp; // original component name set on the intent final ProcessRecord callerApp; // process that sent this final String callerPackage; // who sent this final int callingPid; // the pid of who sent this @@ -82,9 +83,12 @@ class BroadcastRecord extends Binder { pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId); pw.print(prefix); pw.println(intent.toInsecureString()); + if (targetComp != null && targetComp != intent.getComponent()) { + pw.print(prefix); pw.print(" targetComp: "); pw.println(targetComp.toShortString()); + } Bundle bundle = intent.getExtras(); if (bundle != null) { - pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString()); + pw.print(prefix); pw.print(" extras: "); pw.println(bundle.toString()); } pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" "); pw.print(callerApp != null ? callerApp.toShortString() : "null"); @@ -171,6 +175,7 @@ class BroadcastRecord extends Binder { int _userId) { queue = _queue; intent = _intent; + targetComp = _intent.getComponent(); callerApp = _callerApp; callerPackage = _callerPackage; callingPid = _callingPid; |