Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b886419a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Preventing accidental misuse of registerReceiver"

parents fddc2267 ff784956
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.content;

import static org.junit.Assert.fail;

import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class BroadcastReceiverTests {

    private static final int RECEIVER_LIMIT_PER_APP = 1000;
    private static final class EmptyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Empty
        }
    }
    private Context mContext;

    @Before
    public void setUp() {
        mContext = InstrumentationRegistry.getTargetContext();
    }

    @Test
    public void testReceiverLimit() {
        final IntentFilter mockFilter = new IntentFilter("android.content.tests.TestAction");
        try {
            for (int i = 0; i < RECEIVER_LIMIT_PER_APP + 1; i++) {
                mContext.registerReceiver(new EmptyReceiver(), mockFilter);
            }
            fail("No exception thrown when registering "
                    + (RECEIVER_LIMIT_PER_APP + 1) + " receivers");
        } catch (IllegalStateException ise) {
            // Expected
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
        }
    }

    private boolean filterEquals(IntentFilter f1, IntentFilter f2) {
    public static boolean filterEquals(IntentFilter f1, IntentFilter f2) {
        int s1 = f1.countActions();
        int s2 = f2.countActions();
        if (s1 != s2) {
+20 −4
Original line number Diff line number Diff line
@@ -558,6 +558,9 @@ public class ActivityManagerService extends IActivityManager.Stub
    static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
    // Maximum number of receivers an app can register.
    private static final int MAX_RECEIVERS_ALLOWED_PER_APP = 1000;
    // Amount of time after a call to stopAppSwitches() during which we will
    // prevent further untrusted switches from happening.
    static final long APP_SWITCH_DELAY_TIME = 5*1000;
@@ -20542,6 +20545,12 @@ public class ActivityManagerService extends IActivityManager.Stub
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {
                    final int totalReceiversForApp = rl.app.receivers.size();
                    if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                        throw new IllegalStateException("Too many receivers, total of "
                                + totalReceiversForApp + ", registered for pid: "
                                + rl.pid + ", callerPackage: " + callerPackage);
                    }
                    rl.app.receivers.add(rl);
                } else {
                    try {
@@ -20570,11 +20579,18 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            if (rl.containsFilter(filter)) {
                // STOPSHIP: To track if apps are doing this a lot for b/70677313. Change to Slog.w
                Slog.wtf(TAG, "Receiver with filter " + filter
                        + " already registered for pid " + rl.pid
                        + ", callerPackage is " + callerPackage);
            } else {
                rl.add(bf);
                if (!bf.debugCheck()) {
                    Slog.w(TAG, "==> For Dynamic broadcast");
                }
                mReceiverResolver.addFilter(bf);
            }
            // Enqueue broadcasts for all existing stickies that match
            // this filter.
+14 −0
Original line number Diff line number Diff line
@@ -17,11 +17,14 @@
package com.android.server.am;

import android.content.IIntentReceiver;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.IBinder;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.proto.ProtoOutputStream;

import com.android.server.IntentResolver;
import com.android.server.am.proto.ReceiverListProto;

import java.io.PrintWriter;
@@ -67,6 +70,17 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
        owner.unregisterReceiver(receiver);
    }

    public boolean containsFilter(IntentFilter filter) {
        final int N = size();
        for (int i = 0; i < N; i++) {
            final BroadcastFilter f = get(i);
            if (IntentResolver.filterEquals(f, filter)) {
                return true;
            }
        }
        return false;
    }

    void writeToProto(ProtoOutputStream proto, long fieldId) {
        long token = proto.start(fieldId);
        app.writeToProto(proto, ReceiverListProto.APP);