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

Commit 2294db42 authored by Manjeet Rulhania's avatar Manjeet Rulhania Committed by Android (Google) Code Review
Browse files

Merge "Add api to check if an app is in foreground or not."

parents 3b5f1a50 ebdeed13
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -46,6 +46,14 @@ package com.android.server.am {

}

package com.android.server.appop {

  public interface AppOpsManagerLocal {
    method public boolean isUidInForeground(int);
  }

}

package com.android.server.pm {

  public interface PackageManagerLocal {
+36 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.appop;

import android.annotation.SystemApi;

/**
 * In-process app ops API for mainline modules.
 *
 * @hide
 */
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
public interface AppOpsManagerLocal {

    /**
     * Determines if the UID is in foreground in the same way as how foreground runtime
     * permissions work.
     *
     * @return Returns {@code true} if the given UID is in the foreground.
     */
    boolean isUidInForeground(int uid);
}
+10 −0
Original line number Diff line number Diff line
@@ -978,6 +978,7 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
    public void publish() {
        ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
        LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
        LocalServices.addService(AppOpsManagerLocal.class, new AppOpsManagerLocalImpl());
    }

    /** Handler for work when packages are removed or updated */
@@ -6138,6 +6139,15 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
        }
    }

    private final class AppOpsManagerLocalImpl implements AppOpsManagerLocal {
        @Override
        public boolean isUidInForeground(int uid) {
            synchronized (AppOpsService.this) {
                return mUidStateTracker.isUidInForeground(uid);
            }
        }
    }

    private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal {
        @Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
            synchronized (AppOpsService.this) {
+5 −0
Original line number Diff line number Diff line
@@ -88,6 +88,11 @@ interface AppOpsUidStateTracker {
     */
    int getUidState(int uid);

    /**
     * Determines if the uid is in foreground.
     */
    boolean isUidInForeground(int uid);

    /**
     * Given a uid, code, and mode, resolve any foregroundness to MODE_IGNORED or MODE_ALLOWED
     */
+38 −42
Original line number Diff line number Diff line
@@ -24,8 +24,10 @@ import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.ProcessCapability;
import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
@@ -124,67 +126,61 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {

    @Override
    public int evalMode(int uid, int code, int mode) {
        if (mode != AppOpsManager.MODE_FOREGROUND) {
        if (mode != MODE_FOREGROUND) {
            return mode;
        }

        int uidStateValue;
        int capability;
        boolean visibleAppWidget;
        boolean pendingTop;
        boolean tempAllowlist;
        uidStateValue = getUidState(uid);
        capability = getUidCapability(uid);
        visibleAppWidget = getUidVisibleAppWidget(uid);
        pendingTop = mActivityManagerInternal.isPendingTopUid(uid);
        tempAllowlist = mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(uid);

        int result = evalMode(uidStateValue, code, mode, capability, visibleAppWidget, pendingTop,
                tempAllowlist);
        mEventLog.logEvalForegroundMode(uid, uidStateValue, capability, code, result);
        int uidState = getUidState(uid);
        int uidCapability = getUidCapability(uid);
        int result = evalModeInternal(uid, code, uidState, uidCapability);

        mEventLog.logEvalForegroundMode(uid, uidState, uidCapability, code, result);
        return result;
    }

    private static int evalMode(int uidState, int code, int mode, int capability,
            boolean appWidgetVisible, boolean pendingTop, boolean tempAllowlist) {
        if (mode != AppOpsManager.MODE_FOREGROUND) {
            return mode;
        }
    private int evalModeInternal(int uid, int code, int uidState, int uidCapability) {

        if (appWidgetVisible || pendingTop || tempAllowlist) {
        if (getUidVisibleAppWidget(uid) || mActivityManagerInternal.isPendingTopUid(uid)
                || mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(uid)) {
            return MODE_ALLOWED;
        }

        switch (code) {
            case AppOpsManager.OP_FINE_LOCATION:
            case AppOpsManager.OP_COARSE_LOCATION:
            case AppOpsManager.OP_MONITOR_LOCATION:
            case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION:
                if ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) == 0) {
        int opCapability = getOpCapability(code);
        if (opCapability != PROCESS_CAPABILITY_NONE) {
            if ((uidCapability & opCapability) == 0) {
                return MODE_IGNORED;
            } else {
                return MODE_ALLOWED;
            }
            case OP_CAMERA:
                if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) == 0) {
        }

        if (uidState > AppOpsManager.resolveFirstUnrestrictedUidState(code)) {
            return MODE_IGNORED;
                } else {
        }

        return MODE_ALLOWED;
    }

    private int getOpCapability(int opCode) {
        switch (opCode) {
            case AppOpsManager.OP_FINE_LOCATION:
            case AppOpsManager.OP_COARSE_LOCATION:
            case AppOpsManager.OP_MONITOR_LOCATION:
            case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION:
                return PROCESS_CAPABILITY_FOREGROUND_LOCATION;
            case OP_CAMERA:
                return PROCESS_CAPABILITY_FOREGROUND_CAMERA;
            case OP_RECORD_AUDIO:
            case OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO:
                if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) == 0) {
                    return MODE_IGNORED;
                } else {
                    return MODE_ALLOWED;
                return PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
            default:
                return PROCESS_CAPABILITY_NONE;
        }
    }

        if (uidState > AppOpsManager.resolveFirstUnrestrictedUidState(code)) {
            return MODE_IGNORED;
        }

        return MODE_ALLOWED;
    @Override
    public boolean isUidInForeground(int uid) {
        return evalMode(uid, OP_NONE, MODE_FOREGROUND) == MODE_ALLOWED;
    }

    @Override
Loading