Problem description

The Sending non-protected broadcast warning is displayed when the system application sends a broadcast message

This is a warning, actually does not affect the tripartite application receives the broadcast, but the log inside this error message, it is very strange, and the log is deposited in the WTF file, and the number is limited, too many radio may lead to some ANR issue log are covered, so leadership let me from the application layer can try to solve it, So that this error message does not appear.

Find the problem

The first thing to do is to search for the location of the problemAndroidXRef websiteUnder the search83bea660.png

Positioning to/frameworks/base/services/core/Java/com/android/server/am/ActivityManagerService. Java classes, This exception is thrown in checkBroadcastFromSystem.

The checkBroadcastFromSytem function checks whether the broadcastfromsytem is secure. If the broadcastfromBroadcastfromsytem is not secure, it throws a no-protected broadcast exception to alert the application developer.

Why do we have this mechanism?

This is to remind the system application developers to add the broadcast as protected-broadcast, since non-protexted-broadcast broadcasts can be sent by three applications. Proected -broadcast prevents malicious three-party applications from mimicking the system’s applications to emit the same broadcast.


private void checkBroadcastFromSystem(Intent intent, ProcessRecord callerApp,
            String callerPackage, int callingUid, boolean isProtectedBroadcast, List receivers) {
        // Shell sends broadcasts, ignoring checks
        if((intent.getFlags() & Intent.FLAG_RECEIVER_FROM_SHELL) ! =0) {
            // Don't yell about broadcasts sent via shell
            return;
        }
        final String action = intent.getAction();
        // No warning is required for protected broadcast or special actions
        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) || Intent.ACTION_FACTORY_RESET.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) || AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION.equals(action) || AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION.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.
        // The application specifies the package name or Component information for the broadcast receiver. If all recevier have permission requirements on the broadcast sender, the warning is not issued.
        // However, if an application has registered the broadcast but does not require the sender to have the appropriate permissions, the system will issue a non-protected broadcast warning
        if(intent.getPackage() ! =null|| intent.getComponent() ! =null) {
            if (receivers == null || receivers.size() == 0) {
                // Intent is explicit and there's no receivers.
                // This happens, e.g. , when a system component sends a broadcast to
                // its own runtime receiver, and there's no manifest receivers for it,
                // because this method is called twice for each broadcast,
                // for runtime receivers and manifest receivers and the later check would find
                // no receivers.
                return;
            }
            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,
                    newThrowable()); }}Copy the code

In the code above, the checkBroadcastFromSystem method has three checks for broadcasts.

  1. If the Action is emitted by the Shell, it is returned without warning

  2. If the Action is protected-broadcast broadcast or some specified Action, no warning is issued

  3. If the Action specifies a package name or Compononent and only certain applications can receive it, no warning will be issued if all receivers are concerned about the permission based on receiverPermisson

If the system application does not meet the above three conditions, the system will be warned when sending a public broadcast

How do I resolve non-protected broadcast warnings

From the system source layer

  1. CheckBroadcastFromSystem modifications

in

 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) || Intent.ACTION_FACTORY_RESET.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) || AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION.equals(action) || AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION.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;
        }
Copy the code
  1. / frameworks/base/services/core/Java/com/android/server/PM/PackageManagerService. Java# isProtectedBroadcast method modifications

  1. / frameworks/base/core/res/AndroidManifest. XML is increasedprotected-broadcastThe label

Modify at the application level

  1. Add the protected-broadcast tag to androidmanifest.xml and put apK in /system/priv-app

  2. Get all ResolveInfo that received the broadcast and send the broadcast.