Create new BroadcastBehavior annotation.
This will be used to help document the expected behavior of various broadcast actions defined by the OS. Also add logic to PackageParser that will then yell at developers whose manifests are making bad assumptions about which broadcasts they'll receive. Test: builds, boots Bug: 35925551 Change-Id: I059c2bf8aa3ce53d9ff18dcc263db7620cd14bd6
This commit is contained in:
@@ -21,8 +21,11 @@ import static android.Manifest.permission.GET_ACCOUNTS;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.Size;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.annotation.BroadcastBehavior;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
@@ -335,6 +338,8 @@ public class AccountManager {
|
||||
*
|
||||
* @deprecated use #addOnAccountsUpdatedListener to get account updates in runtime.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(includeBackground = true)
|
||||
public static final String LOGIN_ACCOUNTS_CHANGED_ACTION =
|
||||
"android.accounts.LOGIN_ACCOUNTS_CHANGED";
|
||||
|
||||
|
||||
56
core/java/android/annotation/BroadcastBehavior.java
Normal file
56
core/java/android/annotation/BroadcastBehavior.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.annotation;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Description of how the annotated broadcast action behaves.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface BroadcastBehavior {
|
||||
/**
|
||||
* This broadcast will only be delivered to an explicit target.
|
||||
*
|
||||
* @see Intent#setPackage(String)
|
||||
* @see Intent#setComponent(android.content.ComponentName)
|
||||
*/
|
||||
boolean explicitOnly() default false;
|
||||
|
||||
/**
|
||||
* This broadcast will only be delivered to registered receivers.
|
||||
*
|
||||
* @see Intent#FLAG_RECEIVER_REGISTERED_ONLY
|
||||
*/
|
||||
boolean registeredOnly() default false;
|
||||
|
||||
/**
|
||||
* This broadcast will include all {@code AndroidManifest.xml} receivers
|
||||
* regardless of process state.
|
||||
*
|
||||
* @see Intent#FLAG_RECEIVER_INCLUDE_BACKGROUND
|
||||
*/
|
||||
boolean includeBackground() default false;
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.app.admin;
|
||||
|
||||
import android.accounts.AccountManager;
|
||||
import android.annotation.BroadcastBehavior;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
@@ -81,6 +82,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* that other applications can not abuse it.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_DEVICE_ADMIN_ENABLED
|
||||
= "android.app.action.DEVICE_ADMIN_ENABLED";
|
||||
|
||||
@@ -94,6 +96,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* to the user before they disable your admin.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED
|
||||
= "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
|
||||
|
||||
@@ -115,6 +118,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* its intent filter.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_DEVICE_ADMIN_DISABLED
|
||||
= "android.app.action.DEVICE_ADMIN_DISABLED";
|
||||
|
||||
@@ -131,6 +135,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* this broadcast.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_PASSWORD_CHANGED
|
||||
= "android.app.action.ACTION_PASSWORD_CHANGED";
|
||||
|
||||
@@ -147,6 +152,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* this broadcast.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_PASSWORD_FAILED
|
||||
= "android.app.action.ACTION_PASSWORD_FAILED";
|
||||
|
||||
@@ -160,6 +166,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* this broadcast.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_PASSWORD_SUCCEEDED
|
||||
= "android.app.action.ACTION_PASSWORD_SUCCEEDED";
|
||||
|
||||
@@ -173,6 +180,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* this broadcast.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_PASSWORD_EXPIRING
|
||||
= "android.app.action.ACTION_PASSWORD_EXPIRING";
|
||||
|
||||
@@ -187,6 +195,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @see DevicePolicyManager#isLockTaskPermitted(String)
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_LOCK_TASK_ENTERING
|
||||
= "android.app.action.LOCK_TASK_ENTERING";
|
||||
|
||||
@@ -200,6 +209,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @see DevicePolicyManager#isLockTaskPermitted(String)
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_LOCK_TASK_EXITING
|
||||
= "android.app.action.LOCK_TASK_EXITING";
|
||||
|
||||
@@ -232,6 +242,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* <p>Output: Nothing</p>
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
|
||||
"android.app.action.PROFILE_PROVISIONING_COMPLETE";
|
||||
|
||||
@@ -244,6 +255,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_BUGREPORT_SHARING_DECLINED =
|
||||
"android.app.action.BUGREPORT_SHARING_DECLINED";
|
||||
|
||||
@@ -256,6 +268,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_BUGREPORT_FAILED = "android.app.action.BUGREPORT_FAILED";
|
||||
|
||||
/**
|
||||
@@ -266,6 +279,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_BUGREPORT_SHARE =
|
||||
"android.app.action.BUGREPORT_SHARE";
|
||||
|
||||
@@ -274,6 +288,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_SECURITY_LOGS_AVAILABLE
|
||||
= "android.app.action.SECURITY_LOGS_AVAILABLE";
|
||||
|
||||
@@ -283,6 +298,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_NETWORK_LOGS_AVAILABLE
|
||||
= "android.app.action.NETWORK_LOGS_AVAILABLE";
|
||||
|
||||
@@ -314,7 +330,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
public static final String ACTION_USER_ADDED = "android.app.action.USER_ADDED";
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_USER_ADDED = "android.app.action.USER_ADDED";
|
||||
|
||||
/**
|
||||
* Broadcast action: notify the device owner that a user or profile has been removed.
|
||||
@@ -323,6 +340,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_USER_REMOVED = "android.app.action.USER_REMOVED";
|
||||
|
||||
/**
|
||||
@@ -401,6 +419,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE =
|
||||
"android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE";
|
||||
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package android.appwidget;
|
||||
|
||||
import android.annotation.BroadcastBehavior;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -81,12 +84,14 @@ public class AppWidgetManager {
|
||||
*
|
||||
* @see #ACTION_APPWIDGET_CONFIGURE
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK";
|
||||
|
||||
/**
|
||||
* Similar to ACTION_APPWIDGET_PICK, but used from keyguard
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String
|
||||
ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK";
|
||||
|
||||
@@ -133,6 +138,7 @@ public class AppWidgetManager {
|
||||
* @see #ACTION_APPWIDGET_CONFIGURE
|
||||
*
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND";
|
||||
|
||||
/**
|
||||
@@ -157,6 +163,7 @@ public class AppWidgetManager {
|
||||
* and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED}
|
||||
* broadcast.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE";
|
||||
|
||||
/**
|
||||
@@ -290,6 +297,8 @@ public class AppWidgetManager {
|
||||
*
|
||||
* @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";
|
||||
|
||||
/**
|
||||
@@ -302,6 +311,8 @@ public class AppWidgetManager {
|
||||
* AppWidgetProvider.onAppWidgetOptionsChanged(Context context,
|
||||
* AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras)
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS";
|
||||
|
||||
/**
|
||||
@@ -312,6 +323,8 @@ public class AppWidgetManager {
|
||||
*
|
||||
* @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds)
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED";
|
||||
|
||||
/**
|
||||
@@ -322,6 +335,8 @@ public class AppWidgetManager {
|
||||
*
|
||||
* @see AppWidgetProvider#onEnabled AppWidgetProvider.onDisabled(Context context)
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED";
|
||||
|
||||
/**
|
||||
@@ -334,6 +349,8 @@ public class AppWidgetManager {
|
||||
*
|
||||
* @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context)
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED";
|
||||
|
||||
/**
|
||||
@@ -365,6 +382,8 @@ public class AppWidgetManager {
|
||||
*
|
||||
* @see #ACTION_APPWIDGET_HOST_RESTORED
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_APPWIDGET_RESTORED
|
||||
= "android.appwidget.action.APPWIDGET_RESTORED";
|
||||
|
||||
@@ -402,6 +421,8 @@ public class AppWidgetManager {
|
||||
*
|
||||
* @see #ACTION_APPWIDGET_RESTORED
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(explicitOnly = true)
|
||||
public static final String ACTION_APPWIDGET_HOST_RESTORED
|
||||
= "android.appwidget.action.APPWIDGET_HOST_RESTORED";
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.content;
|
||||
|
||||
import android.annotation.AnyRes;
|
||||
import android.annotation.BroadcastBehavior;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
@@ -1991,6 +1992,7 @@ public class Intent implements Parcelable, Cloneable {
|
||||
* This is a protected intent that can only be sent by the system.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
@BroadcastBehavior(includeBackground = true)
|
||||
public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
|
||||
|
||||
/**
|
||||
|
||||
@@ -211,6 +211,14 @@ public class PackageParser {
|
||||
CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
|
||||
}
|
||||
|
||||
private static final boolean LOG_UNSAFE_BROADCASTS = false;
|
||||
|
||||
// Set of broadcast actions that are safe for manifest receivers
|
||||
private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
|
||||
static {
|
||||
SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static class NewPermissionInfo {
|
||||
public final String name;
|
||||
@@ -4240,6 +4248,18 @@ public class PackageParser {
|
||||
if (intent.isVisibleToInstantApp()) {
|
||||
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
|
||||
}
|
||||
if (LOG_UNSAFE_BROADCASTS && receiver
|
||||
&& (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
|
||||
for (int i = 0; i < intent.countActions(); i++) {
|
||||
final String action = intent.getAction(i);
|
||||
if (action == null || !action.startsWith("android.")) continue;
|
||||
if (!SAFE_BROADCASTS.contains(action)) {
|
||||
Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
|
||||
+ owner.packageName + " as requested at: "
|
||||
+ parser.getPositionDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!receiver && parser.getName().equals("preferred")) {
|
||||
ActivityIntentInfo intent = new ActivityIntentInfo(a);
|
||||
if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
|
||||
|
||||
Reference in New Issue
Block a user