平台:

rk3288 + android 7.1

Android 对广播有明显的限定权限:

系统应用仅发送指定受保护广播.

 E/ActivityManager: Sending non-protected broadcast android.intent.action.NEW_BROADCAST from system 1437:com.android.shell/2000 pkg com.android.shell     java.lang.Throwable         at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:18169)         at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18651)         at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:18833)         at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:499)         at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2911)         at android.os.Binder.execTransact(Binder.java:565)

相关源码:

|-- frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java    private void checkBroadcastFromSystem(Intent intent, ProcessRecord callerApp,            String callerPackage, int callingUid, boolean isProtectedBroadcast, List receivers) {        final String action = intent.getAction();        if (isProtectedBroadcast                || Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)                || Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(action)                || Intent.ACTION_MEDIA_BUTTON.equals(action)                || Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)                || Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(action)                || Intent.ACTION_MASTER_CLEAR.equals(action)                || AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)                || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)                || LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)                || TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)                || SuggestionSpan.ACTION_SUGGESTION_PICKED.equals(action)) {            // Broadcast is either protected, or it's a public action that            // we've relaxed, so it's fine for system internals to send.            return;        }        // This broadcast may be a problem...  but there are often system components that        // want to send an internal broadcast to themselves, which is annoying to have to        // explicitly list each action as a protected broadcast, so we will check for that        // one safe case and allow it: an explicit broadcast, only being received by something        // that has protected itself.        if (receivers != null && receivers.size() > 0                && (intent.getPackage() != null || intent.getComponent() != null)) {            boolean allProtected = true;            for (int i = receivers.size()-1; i >= 0; i--) {                Object target = receivers.get(i);                if (target instanceof ResolveInfo) {                    ResolveInfo ri = (ResolveInfo)target;                    if (ri.activityInfo.exported && ri.activityInfo.permission == null) {                        allProtected = false;                        break;                    }                } else {                    BroadcastFilter bf = (BroadcastFilter)target;                    if (bf.requiredPermission == null) {                        allProtected = false;                        break;                    }                }            }            if (allProtected) {                // All safe!                return;            }        }        // The vast majority of broadcasts sent from system internals        // should be protected to avoid security holes, so yell loudly        // to ensure we examine these cases.        if (callerApp != null) {            Log.wtf(TAG, "Sending non-protected broadcast " + action                            + " from system " + callerApp.toShortString() + " pkg " + callerPackage,                    new Throwable());        } else {            Log.wtf(TAG, "Sending non-protected broadcast " + action                            + " from system uid " + UserHandle.formatUid(callingUid)                            + " pkg " + callerPackage,                    new Throwable());        }    }
广播还是可以发出去的, 只是会有LOG提示, 不影响实际功能.

不允许第三方应用发送受保护广播
非系统APK 发送了系统广播:

Process: com.androidtest, PID: 1640java.lang.RuntimeException: Unable to start activity ComponentInfo{com.androidtest/com.androidtest.MainActivity}: java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.NEW_BROADCAST from pid=1640, uid=10056    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2671)    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732)    at android.app.ActivityThread.-wrap12(ActivityThread.java)    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1483)    at android.os.Handler.dispatchMessage(Handler.java:102)    at android.os.Looper.loop(Looper.java:154)    at android.app.ActivityThread.main(ActivityThread.java:6141)    at java.lang.reflect.Method.invoke(Native Method)    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802) Caused by: java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.NEW_BROADCAST from pid=1640, uid=10056    at android.os.Parcel.readException(Parcel.java:1684)    at android.os.Parcel.readException(Parcel.java:1637)    at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:3565)    at android.app.ContextImpl.sendBroadcast(ContextImpl.java:881)    at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:421)    at com.androidtest.MainActivity.testBroadcast(MainActivity.java:131)    at com.androidtest.MainActivity.onCreate(MainActivity.java:41)    at android.app.Activity.performCreate(Activity.java:6709)    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2624)    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732)     at android.app.ActivityThread.-wrap12(ActivityThread.java)     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1483)     at android.os.Handler.dispatchMessage(Handler.java:102)     at android.os.Looper.loop(Looper.java:154)     at android.app.ActivityThread.main(ActivityThread.java:6141)     at java.lang.reflect.Method.invoke(Native Method)     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802) 

异常代码:

|-- frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java    final int broadcastIntentLocked(ProcessRecord callerApp,            String callerPackage, Intent intent, String resolvedType,            IIntentReceiver resultTo, int resultCode, String resultData,            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,            boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {        intent = new Intent(intent);        // By default broadcasts do not go to stopped apps.        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);        // If we have not finished booting, don't allow this to launch new processes.        if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);        }        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,                (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent                + " ordered=" + ordered + " userid=" + userId);        if ((resultTo != null) && !ordered) {            Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");        }        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,                ALLOW_NON_FULL, "broadcast", callerPackage);        // Make sure that the user who is receiving this broadcast is running.        // If not, we will just skip it. Make an exception for shutdown broadcasts        // and upgrade steps.        if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) {            if ((callingUid != Process.SYSTEM_UID                    || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)                    && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {                Slog.w(TAG, "Skipping broadcast of " + intent                        + ": user " + userId + " is stopped");                return ActivityManager.BROADCAST_FAILED_USER_STOPPED;            }        }        BroadcastOptions brOptions = null;        if (bOptions != null) {            brOptions = new BroadcastOptions(bOptions);            if (brOptions.getTemporaryAppWhitelistDuration() > 0) {                // See if the caller is allowed to do this.  Note we are checking against                // the actual real caller (not whoever provided the operation as say a                // PendingIntent), because that who is actually supplied the arguments.                if (checkComponentPermission(                        android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,                        Binder.getCallingPid(), Binder.getCallingUid(), -1, true)                        != PackageManager.PERMISSION_GRANTED) {                    String msg = "Permission Denial: " + intent.getAction()                            + " broadcast from " + callerPackage + " (pid=" + callingPid                            + ", uid=" + callingUid + ")"                            + " requires "                            + android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;                    Slog.w(TAG, msg);                    throw new SecurityException(msg);                }            }        }        // Verify that protected broadcasts are only being sent by system code,        // and that system code is only sending protected broadcasts.        final String action = intent.getAction();        final boolean isProtectedBroadcast;        try {            isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);        } catch (RemoteException e) {            Slog.w(TAG, "Remote exception", e);            return ActivityManager.BROADCAST_SUCCESS;        }        final boolean isCallerSystem;        switch (UserHandle.getAppId(callingUid)) {            case Process.ROOT_UID:            case Process.SYSTEM_UID:case Process.SHELL_UID://AnsonCode make shell send system broadcast            case Process.PHONE_UID:            case Process.BLUETOOTH_UID:            case Process.NFC_UID:                isCallerSystem = true;                break;            default:                isCallerSystem = (callerApp != null) && callerApp.persistent;                break;        }        // First line security check before anything else: stop non-system apps from        // sending protected broadcasts.        if (!isCallerSystem) {            if (isProtectedBroadcast) {//限制受保护广播, 并且抛出异常给APP.                String msg = "Permission Denial: not allowed to send broadcast "                        + action + " from pid="                        + callingPid + ", uid=" + callingUid;                Slog.w(TAG, msg);                throw new SecurityException(msg);            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)                    || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {                // 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 (callerPackage == null) {                    String msg = "Permission Denial: not allowed to send broadcast "                            + action + " 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(                            callerPackage)) {                        String msg = "Permission Denial: not allowed to send broadcast "                                + action + " to "                                + intent.getComponent().getPackageName() + " from "                                + callerPackage;                        Slog.w(TAG, msg);                        throw new SecurityException(msg);                    }                } else {                    // Limit broadcast to their own package.                    intent.setPackage(callerPackage);                }            }        }...

使SHELL可以发送系统广播:

|-- frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java@@ -18251,6 +18251,7 @@ public final class ActivityManagerService extends ActivityManagerNative         switch (UserHandle.getAppId(callingUid)) {             case Process.ROOT_UID:             case Process.SYSTEM_UID:+            case Process.SHELL_UID://make shell send system broadcast             case Process.PHONE_UID:             case Process.BLUETOOTH_UID:             case Process.NFC_UID:

添加广播以支持系统应用发送:
|-- frameworks/base/core/res/AndroidManifest.xml

@@ -143,6 +143,7 @@     <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" />     <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />     <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />+    <protected-broadcast android:name="android.intent.action.NEW_BROADCAST"/>

更多相关文章

  1. Android一键锁屏代码
  2. Android(安卓)入门知识点梳理之一 四大组件
  3. 初学Android,开机自启动的Service(七十三)
  4. C# android base-64 字符数组的无效长度
  5. 【Android】Android中广播的基本使用
  6. 文章分享:Android四大组件详解
  7. [Android]后台Service 弹出自定义dialog
  8. Android的framework层音量控制原理分析--hot(key)处理
  9. androidの亮屏,灭屏,解锁广播使用

随机推荐

  1. Android(安卓)Studio如何修改快捷键
  2. android 发布正式版时用Gradle移除日志打
  3. Android报错集锦之二:Android studio 3.0
  4. Android——Intent动作汇总
  5. 设置图片缩放方法失效 解决办法设置andro
  6. android获取CPU参数(命令行方式)
  7. Android简单音乐播放实例
  8. Android SDK文档如何查找
  9. Android 获取扫码枪的扫描内容
  10. Android常见问题及讨论(41-45)