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

Commit ccaf79d2 authored by Jing Ji's avatar Jing Ji
Browse files

Add tracking on abusive broadcast and service binding requests

In case of excessive amount of outgoing broadcast/service binding
requests from a background app, move the app to restricted bucket.
The exemptions in previous CL still applys here.

Bug: 200326767
Test: atest FrameworksMockingServicesTests:BackgroundRestrictionTest
Change-Id: I2ec82f26bf2a72e2201b140979be09794adedf47
parent 8a3b17f0
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -776,4 +776,34 @@ public abstract class ActivityManagerInternal {
     */
    public abstract void addForegroundServiceStateListener(
            @NonNull ForegroundServiceStateListener listener);

    /**
     * A listener interface, which will be notified on the package sends a broadcast.
     */
    public interface BroadcastEventListener {
        /**
         * Called when the given package/uid is sending a broadcast.
         */
        void onSendingBroadcast(String packageName, int uid);
    }

    /**
     * Register the broadcast event listener callback.
     */
    public abstract void addBroadcastEventListener(@NonNull BroadcastEventListener listener);

    /**
     * A listener interface, which will be notified on the package binding to a service.
     */
    public interface BindServiceEventListener {
        /**
         * Called when the given package/uid is binding to a service
         */
        void onBindingService(String packageName, int uid);
    }

    /**
     * Register the bind service event listener callback.
     */
    public abstract void addBindServiceEventListener(@NonNull BindServiceEventListener listener);
}
+12 −0
Original line number Diff line number Diff line
@@ -2975,9 +2975,21 @@ public final class ActiveServices {
            Binder.restoreCallingIdentity(origId);
        }

        notifyBindingServiceEventLocked(callerApp, callingPackage);

        return 1;
    }

    @GuardedBy("mAm")
    private void notifyBindingServiceEventLocked(ProcessRecord callerApp, String callingPackage) {
        final ApplicationInfo ai = callerApp.info;
        final String callerPackage = ai != null ? ai.packageName : callingPackage;
        if (callerPackage != null) {
            mAm.mHandler.obtainMessage(ActivityManagerService.DISPATCH_BINDING_SERVICE_EVENT,
                    callerApp.uid, 0, callerPackage).sendToTarget();
        }
    }

    private void maybeLogBindCrossProfileService(
            int userId, String callingPackage, int callingUid) {
        if (UserHandle.isCore(callingUid)) {
+37 −0
Original line number Diff line number Diff line
@@ -156,6 +156,8 @@ import android.app.ActivityManager.ProcessCapability;
import android.app.ActivityManager.RestrictionLevel;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerInternal.BindServiceEventListener;
import android.app.ActivityManagerInternal.BroadcastEventListener;
import android.app.ActivityManagerInternal.ForegroundServiceStateListener;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.ActivityThread;
@@ -439,6 +441,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
@@ -1380,6 +1383,18 @@ public class ActivityManagerService extends IActivityManager.Stub
    final ArrayList<ForegroundServiceStateListener> mForegroundServiceStateListeners =
            new ArrayList<>();
    /**
     * The list of broadcast event listeners.
     */
    final CopyOnWriteArrayList<BroadcastEventListener> mBroadcastEventListeners =
            new CopyOnWriteArrayList<>();
    /**
     * The list of bind service event listeners.
     */
    final CopyOnWriteArrayList<BindServiceEventListener> mBindServiceEventListeners =
            new CopyOnWriteArrayList<>();
    /**
     * Set if the systemServer made a call to enterSafeMode.
     */
@@ -1522,6 +1537,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    static final int KILL_APP_ZYGOTE_MSG = 71;
    static final int BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG = 72;
    static final int WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG = 73;
    static final int DISPATCH_SENDING_BROADCAST_EVENT = 74;
    static final int DISPATCH_BINDING_SERVICE_EVENT = 75;
    static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1839,6 +1856,14 @@ public class ActivityManagerService extends IActivityManager.Stub
                        ((ContentProviderRecord) msg.obj).onProviderPublishStatusLocked(false);
                    }
                } break;
                case DISPATCH_SENDING_BROADCAST_EVENT: {
                    mBroadcastEventListeners.forEach(l ->
                            l.onSendingBroadcast((String) msg.obj, msg.arg1));
                } break;
                case DISPATCH_BINDING_SERVICE_EVENT: {
                    mBindServiceEventListeners.forEach(l ->
                            l.onBindingService((String) msg.obj, msg.arg1));
                } break;
            }
        }
    }
@@ -16874,6 +16899,18 @@ public class ActivityManagerService extends IActivityManager.Stub
                mForegroundServiceStateListeners.add(listener);
            }
        }
        @Override
        public void addBroadcastEventListener(@NonNull BroadcastEventListener listener) {
            // It's a CopyOnWriteArrayList, so no lock is needed.
            mBroadcastEventListeners.add(listener);
        }
        @Override
        public void addBindServiceEventListener(@NonNull BindServiceEventListener listener) {
            // It's a CopyOnWriteArrayList, so no lock is needed.
            mBindServiceEventListeners.add(listener);
        }
    }
    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
+142 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 com.android.server.am;

import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.AppRestrictionController.DEVICE_CONFIG_SUBNAMESPACE_PREFIX;
import static com.android.server.am.BaseAppStateTracker.ONE_DAY;

import android.annotation.NonNull;
import android.app.ActivityManagerInternal.BindServiceEventListener;
import android.content.Context;

import com.android.server.am.AppBindServiceEventsTracker.AppBindServiceEventsPolicy;
import com.android.server.am.BaseAppStateTimeSlotEventsTracker.SimpleAppStateTimeslotEvents;
import com.android.server.am.BaseAppStateTracker.Injector;

import java.io.PrintWriter;
import java.lang.reflect.Constructor;

final class AppBindServiceEventsTracker extends BaseAppStateTimeSlotEventsTracker
        <AppBindServiceEventsPolicy, SimpleAppStateTimeslotEvents>
        implements BindServiceEventListener {

    static final String TAG = TAG_WITH_CLASS_NAME ? "AppBindServiceEventsTracker" : TAG_AM;

    static final boolean DEBUG_APP_STATE_BIND_SERVICE_EVENT_TRACKER = false;

    AppBindServiceEventsTracker(Context context, AppRestrictionController controller) {
        this(context, controller, null, null);
    }

    AppBindServiceEventsTracker(Context context, AppRestrictionController controller,
            Constructor<? extends Injector<AppBindServiceEventsPolicy>> injector,
            Object outerContext) {
        super(context, controller, injector, outerContext);
        mInjector.setPolicy(new AppBindServiceEventsPolicy(mInjector, this));
    }

    @Override
    public void onBindingService(String packageName, int uid) {
        if (mInjector.getPolicy().isEnabled()) {
            onNewEvent(packageName, uid);
        }
    }

    @Override
    void onSystemReady() {
        super.onSystemReady();
        mInjector.getActivityManagerInternal().addBindServiceEventListener(this);
    }

    @Override
    public SimpleAppStateTimeslotEvents createAppStateEvents(int uid, String packageName) {
        return new SimpleAppStateTimeslotEvents(uid, packageName,
                mInjector.getPolicy().getTimeSlotSize(), TAG, mInjector.getPolicy());
    }

    @Override
    public SimpleAppStateTimeslotEvents createAppStateEvents(SimpleAppStateTimeslotEvents other) {
        return new SimpleAppStateTimeslotEvents(other);
    }

    @Override
    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix);
        pw.println("APP BIND SERVICE EVENT TRACKER:");
        super.dump(pw, "  " + prefix);
    }

    static final class AppBindServiceEventsPolicy
            extends BaseAppStateTimeSlotEventsPolicy<AppBindServiceEventsTracker> {
        /**
         * Whether or not we should enable the monitoring on abusive service bindings requests.
         */
        static final String KEY_BG_BIND_SVC_MONITOR_ENABLED =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "bind_svc_monitor_enabled";

        /**
         * The size of the sliding window in which the number of service binding requests is checked
         * against the threshold.
         */
        static final String KEY_BG_BIND_SVC_WINDOW =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "bind_svc_window";

        /**
         * The threshold at where the number of service binding requests are considered as
         * "excessive" within the given window.
         */
        static final String KEY_BG_EX_BIND_SVC_THRESHOLD =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "ex_bind_svc_threshold";

        /**
         * Default value to {@link #mTrackerEnabled}.
         */
        static final boolean DEFAULT_BG_BIND_SVC_MONITOR_ENABLED = true;

        /**
         * Default value to {@link #mMaxTrackingDuration}.
         */
        static final long DEFAULT_BG_BIND_SVC_WINDOW = ONE_DAY;

        /**
         * Default value to {@link #mNumOfEventsThreshold}.
         */
        static final int DEFAULT_BG_EX_BIND_SVC_THRESHOLD = 10_000;

        AppBindServiceEventsPolicy(@NonNull Injector injector,
                @NonNull AppBindServiceEventsTracker tracker) {
            super(injector, tracker,
                    KEY_BG_BIND_SVC_MONITOR_ENABLED, DEFAULT_BG_BIND_SVC_MONITOR_ENABLED,
                    KEY_BG_BIND_SVC_WINDOW, DEFAULT_BG_BIND_SVC_WINDOW,
                    KEY_BG_EX_BIND_SVC_THRESHOLD, DEFAULT_BG_EX_BIND_SVC_THRESHOLD);
        }

        @Override
        String getEventName() {
            return "bindservice";
        }

        @Override
        void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
            pw.println("APP BIND SERVICE EVENT TRACKER POLICY SETTINGS:");
            super.dump(pw, "  " + prefix);
        }
    }
}
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 com.android.server.am;

import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.AppRestrictionController.DEVICE_CONFIG_SUBNAMESPACE_PREFIX;
import static com.android.server.am.BaseAppStateTracker.ONE_DAY;

import android.annotation.NonNull;
import android.app.ActivityManagerInternal.BroadcastEventListener;
import android.content.Context;

import com.android.server.am.AppBroadcastEventsTracker.AppBroadcastEventsPolicy;
import com.android.server.am.BaseAppStateTimeSlotEventsTracker.SimpleAppStateTimeslotEvents;
import com.android.server.am.BaseAppStateTracker.Injector;

import java.io.PrintWriter;
import java.lang.reflect.Constructor;

final class AppBroadcastEventsTracker extends BaseAppStateTimeSlotEventsTracker
        <AppBroadcastEventsPolicy, SimpleAppStateTimeslotEvents> implements BroadcastEventListener {

    static final String TAG = TAG_WITH_CLASS_NAME ? "AppBroadcastEventsTracker" : TAG_AM;

    static final boolean DEBUG_APP_STATE_BROADCAST_EVENT_TRACKER = false;

    AppBroadcastEventsTracker(Context context, AppRestrictionController controller) {
        this(context, controller, null, null);
    }

    AppBroadcastEventsTracker(Context context, AppRestrictionController controller,
            Constructor<? extends Injector<AppBroadcastEventsPolicy>> injector,
            Object outerContext) {
        super(context, controller, injector, outerContext);
        mInjector.setPolicy(new AppBroadcastEventsPolicy(mInjector, this));
    }

    @Override
    public void onSendingBroadcast(String packageName, int uid) {
        if (mInjector.getPolicy().isEnabled()) {
            onNewEvent(packageName, uid);
        }
    }

    @Override
    void onSystemReady() {
        super.onSystemReady();
        mInjector.getActivityManagerInternal().addBroadcastEventListener(this);
    }

    @Override
    public SimpleAppStateTimeslotEvents createAppStateEvents(int uid, String packageName) {
        return new SimpleAppStateTimeslotEvents(uid, packageName,
                mInjector.getPolicy().getTimeSlotSize(), TAG, mInjector.getPolicy());
    }

    @Override
    public SimpleAppStateTimeslotEvents createAppStateEvents(SimpleAppStateTimeslotEvents other) {
        return new SimpleAppStateTimeslotEvents(other);
    }

    @Override
    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix);
        pw.println("APP BROADCAST EVENT TRACKER:");
        super.dump(pw, "  " + prefix);
    }

    static final class AppBroadcastEventsPolicy
            extends BaseAppStateTimeSlotEventsPolicy<AppBroadcastEventsTracker> {
        /**
         * Whether or not we should enable the monitoring on abusive broadcasts.
         */
        static final String KEY_BG_BROADCAST_MONITOR_ENABLED =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "broadcast_monitor_enabled";

        /**
         * The size of the sliding window in which the number of broadcasts is checked
         * against the threshold.
         */
        static final String KEY_BG_BROADCAST_WINDOW =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "broadcast_window";

        /**
         * The threshold at where the number of broadcasts are considered as "excessive"
         * within the given window.
         */
        static final String KEY_BG_EX_BROADCAST_THRESHOLD =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "ex_broadcast_threshold";

        /**
         * Default value to {@link #mTrackerEnabled}.
         */
        static final boolean DEFAULT_BG_BROADCAST_MONITOR_ENABLED = true;

        /**
         * Default value to {@link #mMaxTrackingDuration}.
         */
        static final long DEFAULT_BG_BROADCAST_WINDOW = ONE_DAY;

        /**
         * Default value to {@link #mNumOfEventsThreshold}.
         */
        static final int DEFAULT_BG_EX_BROADCAST_THRESHOLD = 10_000;

        AppBroadcastEventsPolicy(@NonNull Injector injector,
                @NonNull AppBroadcastEventsTracker tracker) {
            super(injector, tracker,
                    KEY_BG_BROADCAST_MONITOR_ENABLED, DEFAULT_BG_BROADCAST_MONITOR_ENABLED,
                    KEY_BG_BROADCAST_WINDOW, DEFAULT_BG_BROADCAST_WINDOW,
                    KEY_BG_EX_BROADCAST_THRESHOLD, DEFAULT_BG_EX_BROADCAST_THRESHOLD);
        }

        @Override
        String getEventName() {
            return "broadcast";
        }

        @Override
        void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
            pw.println("APP BROADCAST EVENT TRACKER POLICY SETTINGS:");
            super.dump(pw, "  " + prefix);
        }
    }
}
Loading