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

Commit b06e9190 authored by Chris Tate's avatar Chris Tate Committed by Android (Google) Code Review
Browse files

Merge "Infra for SysUI to monitor FGSes"

parents b14671ef 59ee488c
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import android.app.GrantedUriPermission;
import android.app.IApplicationThread;
import android.app.IApplicationThread;
import android.app.IActivityController;
import android.app.IActivityController;
import android.app.IAppTask;
import android.app.IAppTask;
import android.app.IForegroundServiceObserver;
import android.app.IInstrumentationWatcher;
import android.app.IInstrumentationWatcher;
import android.app.IProcessObserver;
import android.app.IProcessObserver;
import android.app.IServiceConnection;
import android.app.IServiceConnection;
@@ -279,6 +280,8 @@ interface IActivityManager {
    boolean clearApplicationUserData(in String packageName, boolean keepState,
    boolean clearApplicationUserData(in String packageName, boolean keepState,
            in IPackageDataObserver observer, int userId);
            in IPackageDataObserver observer, int userId);
    void makeServicesNonForeground(in String packageName, int userId);
    void makeServicesNonForeground(in String packageName, int userId);
    /** Returns {@code false} if the callback could not be registered, {@true} otherwise. */
    boolean registerForegroundServiceObserver(in IForegroundServiceObserver callback);
    @UnsupportedAppUsage
    @UnsupportedAppUsage
    void forceStopPackage(in String packageName, int userId);
    void forceStopPackage(in String packageName, int userId);
    boolean killPids(in int[] pids, in String reason, boolean secure);
    boolean killPids(in int[] pids, in String reason, boolean secure);
+31 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2021 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.app;

/**
 * Notify the client of all changes to services' foreground state.
 * @param serviceToken unique identifier for a service instance
 * @param packageName identifies the app hosting the service
 * @param userId identifies the started user in which the app is running
 * @param isForeground whether the service is in the "foreground" mode now, i.e.
 *     whether it is an FGS
 *
 * @hide
 */
oneway interface IForegroundServiceObserver {
    void onForegroundStateChanged(in IBinder serviceToken, in String packageName, int userId, boolean isForeground);
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@ per-file IActivityController.aidl = file:/services/core/java/com/android/server/
per-file IActivityManager.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IActivityManager.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IApplicationThread.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IApplicationThread.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IAppTraceRetriever.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IAppTraceRetriever.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IForegroundServiceObserver.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IInstrumentationWatcher.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IInstrumentationWatcher.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IntentService.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IntentService.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IServiceConnection.aidl = file:/services/core/java/com/android/server/am/OWNERS
per-file IServiceConnection.aidl = file:/services/core/java/com/android/server/am/OWNERS
+70 −1
Original line number Original line Diff line number Diff line
@@ -90,6 +90,7 @@ import android.app.AppOpsManager;
import android.app.ForegroundServiceDidNotStartInTimeException;
import android.app.ForegroundServiceDidNotStartInTimeException;
import android.app.ForegroundServiceStartNotAllowedException;
import android.app.ForegroundServiceStartNotAllowedException;
import android.app.IApplicationThread;
import android.app.IApplicationThread;
import android.app.IForegroundServiceObserver;
import android.app.IServiceConnection;
import android.app.IServiceConnection;
import android.app.Notification;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.NotificationManager;
@@ -128,6 +129,7 @@ import android.os.PowerExemptionManager;
import android.os.PowerExemptionManager.ReasonCode;
import android.os.PowerExemptionManager.ReasonCode;
import android.os.Process;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemClock;
@@ -266,6 +268,12 @@ public final class ActiveServices {
     */
     */
    final SparseLongArray mFgsDeferralEligible = new SparseLongArray();
    final SparseLongArray mFgsDeferralEligible = new SparseLongArray();


    /**
     * Foreground service observers: track what apps have FGSes
     */
    final RemoteCallbackList<IForegroundServiceObserver> mFgsObservers =
            new RemoteCallbackList<>();

    /**
    /**
     * Map of services that are asked to be brought up (start/binding) but not ready to.
     * Map of services that are asked to be brought up (start/binding) but not ready to.
     */
     */
@@ -1382,6 +1390,10 @@ public final class ActiveServices {
        return false;
        return false;
    }
    }


    /**
     * Put the named service into the foreground mode
     */
    @GuardedBy("mAm")
    public void setServiceForegroundLocked(ComponentName className, IBinder token,
    public void setServiceForegroundLocked(ComponentName className, IBinder token,
            int id, Notification notification, int flags, int foregroundServiceType) {
            int id, Notification notification, int flags, int foregroundServiceType) {
        final int userId = UserHandle.getCallingUserId();
        final int userId = UserHandle.getCallingUserId();
@@ -1746,6 +1758,7 @@ public final class ActiveServices {
    /**
    /**
     * @param id Notification ID.  Zero === exit foreground state for the given service.
     * @param id Notification ID.  Zero === exit foreground state for the given service.
     */
     */
    @GuardedBy("mAm")
    private void setServiceForegroundInnerLocked(final ServiceRecord r, int id,
    private void setServiceForegroundInnerLocked(final ServiceRecord r, int id,
            Notification notification, int flags, int foregroundServiceType) {
            Notification notification, int flags, int foregroundServiceType) {
        if (id != 0) {
        if (id != 0) {
@@ -1981,6 +1994,7 @@ public final class ActiveServices {
                    }
                    }
                    // Even if the service is already a FGS, we need to update the notification,
                    // Even if the service is already a FGS, we need to update the notification,
                    // so we need to call it again.
                    // so we need to call it again.
                    signalForegroundServiceObserversLocked(r);
                    r.postNotification();
                    r.postNotification();
                    if (r.app != null) {
                    if (r.app != null) {
                        updateServiceForegroundLocked(psr, true);
                        updateServiceForegroundLocked(psr, true);
@@ -2060,6 +2074,7 @@ public final class ActiveServices {
                        r.mFgsExitTime > r.mFgsEnterTime
                        r.mFgsExitTime > r.mFgsEnterTime
                                ? (int)(r.mFgsExitTime - r.mFgsEnterTime) : 0);
                                ? (int)(r.mFgsExitTime - r.mFgsEnterTime) : 0);
                r.mFgsNotificationWasDeferred = false;
                r.mFgsNotificationWasDeferred = false;
                signalForegroundServiceObserversLocked(r);
                resetFgsRestrictionLocked(r);
                resetFgsRestrictionLocked(r);
                mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
                mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
                if (r.app != null) {
                if (r.app != null) {
@@ -4552,7 +4567,8 @@ public final class ActiveServices {
        }
        }


        cancelForegroundNotificationLocked(r);
        cancelForegroundNotificationLocked(r);
        if (r.isForeground) {
        final boolean exitingFg = r.isForeground;
        if (exitingFg) {
            decActiveForegroundAppLocked(smap, r);
            decActiveForegroundAppLocked(smap, r);
            synchronized (mAm.mProcessStats.mLock) {
            synchronized (mAm.mProcessStats.mLock) {
                ServiceState stracker = r.getTracker();
                ServiceState stracker = r.getTracker();
@@ -4578,6 +4594,11 @@ public final class ActiveServices {
        r.foregroundId = 0;
        r.foregroundId = 0;
        r.foregroundNoti = null;
        r.foregroundNoti = null;
        resetFgsRestrictionLocked(r);
        resetFgsRestrictionLocked(r);
        // Signal FGS observers *after* changing the isForeground state, and
        // only if this was an actual state change.
        if (exitingFg) {
            signalForegroundServiceObserversLocked(r);
        }


        // Clear start entries.
        // Clear start entries.
        r.clearDeliveredStartsLocked();
        r.clearDeliveredStartsLocked();
@@ -5133,6 +5154,54 @@ public final class ActiveServices {
        }
        }
    }
    }


    @GuardedBy("mAm")
    private void signalForegroundServiceObserversLocked(ServiceRecord r) {
        final int num = mFgsObservers.beginBroadcast();
        for (int i = 0; i < num; i++) {
            try {
                mFgsObservers.getBroadcastItem(i).onForegroundStateChanged(r,
                        r.appInfo.packageName, r.userId, r.isForeground);
            } catch (RemoteException e) {
                // Will be unregistered automatically by RemoteCallbackList's dead-object
                // tracking, so nothing we need to do here.
            }
        }
        mFgsObservers.finishBroadcast();
    }

    @GuardedBy("mAm")
    boolean registerForegroundServiceObserverLocked(final int callingUid,
            IForegroundServiceObserver callback) {
        // We always tell the newly-registered observer about any current FGSes.  The
        // most common case for this is a SysUI crash & relaunch; it needs to
        // reconstruct its tracking of stoppable-FGS-hosting apps.
        try {
            final int mapSize = mServiceMap.size();
            for (int mapIndex = 0; mapIndex < mapSize; mapIndex++) {
                final ServiceMap smap = mServiceMap.valueAt(mapIndex);
                if (smap != null) {
                    final int numServices = smap.mServicesByInstanceName.size();
                    for (int i = 0; i < numServices; i++) {
                        final ServiceRecord sr = smap.mServicesByInstanceName.valueAt(i);
                        if (sr.isForeground && callingUid == sr.appInfo.uid) {
                            callback.onForegroundStateChanged(sr, sr.appInfo.packageName,
                                    sr.userId, true);
                        }
                    }
                }
            }
            // Callback is fine, go ahead and record it
            mFgsObservers.register(callback);
        } catch (RemoteException e) {
            // Whoops, something wrong with the callback.  Don't register it, and
            // report error back to the caller.
            Slog.e(TAG_SERVICE, "Bad FGS observer from uid " + callingUid);
            return false;
        }

        return true;
    }

    void forceStopPackageLocked(String packageName, int userId) {
    void forceStopPackageLocked(String packageName, int userId) {
        ServiceMap smap = mServiceMap.get(userId);
        ServiceMap smap = mServiceMap.get(userId);
        if (smap != null && smap.mActiveForegroundApps.size() > 0) {
        if (smap != null && smap.mActiveForegroundApps.size() > 0) {
+25 −2
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
import static android.Manifest.permission.FILTER_EVENTS;
import static android.Manifest.permission.FILTER_EVENTS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS;
@@ -168,6 +169,7 @@ import android.app.ContentProviderHolder;
import android.app.IActivityController;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IActivityManager;
import android.app.IApplicationThread;
import android.app.IApplicationThread;
import android.app.IForegroundServiceObserver;
import android.app.IInstrumentationWatcher;
import android.app.IInstrumentationWatcher;
import android.app.INotificationManager;
import android.app.INotificationManager;
import android.app.IProcessObserver;
import android.app.IProcessObserver;
@@ -3754,12 +3756,12 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    @Override
    public void makeServicesNonForeground(final String packageName, int userId) {
    public void makeServicesNonForeground(final String packageName, int userId) {
        if (checkCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
        if (checkCallingPermission(MANAGE_ACTIVITY_TASKS)
                != PackageManager.PERMISSION_GRANTED) {
                != PackageManager.PERMISSION_GRANTED) {
            String msg = "Permission Denial: makeServicesNonForeground() from pid="
            String msg = "Permission Denial: makeServicesNonForeground() from pid="
                    + Binder.getCallingPid()
                    + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid()
                    + ", uid=" + Binder.getCallingUid()
                    + " requires " + android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
                    + " requires " + MANAGE_ACTIVITY_TASKS;
            Slog.w(TAG, msg);
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
            throw new SecurityException(msg);
        }
        }
@@ -3775,6 +3777,27 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        }
    }
    }
    @Override
    public boolean registerForegroundServiceObserver(IForegroundServiceObserver callback) {
        final int callingUid = Binder.getCallingUid();
        final int permActivityTasks = checkCallingPermission(MANAGE_ACTIVITY_TASKS);
        final int permAcrossUsersFull = checkCallingPermission(INTERACT_ACROSS_USERS_FULL);
        if (permActivityTasks != PackageManager.PERMISSION_GRANTED
                || permAcrossUsersFull != PERMISSION_GRANTED) {
            String msg = "Permission Denial: registerForegroundServiceObserver() from pid="
                    + Binder.getCallingPid()
                    + ", uid=" + callingUid
                    + " requires " + MANAGE_ACTIVITY_TASKS
                    + " and " + INTERACT_ACROSS_USERS_FULL;
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
        synchronized (this) {
            return mServices.registerForegroundServiceObserverLocked(callingUid, callback);
        }
    }
    @Override
    @Override
    public void forceStopPackage(final String packageName, int userId) {
    public void forceStopPackage(final String packageName, int userId) {
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)