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

Commit ebfad50c authored by Hui Yu's avatar Hui Yu
Browse files

Allow FGS started from MediaButtonReceiver to have while-in-use

permissions.

1. Create FgsWhileInUseTempAllowList, the uid on this list is allowed to
have while-in-use permission when the FGS is started from background for
a duration of time.
2. When media button is pressed, the targetUid is added to
FgsWhileInUseTempAllowList for the duration of 10 seconds, this way the
targetUid can start FGS from background and have while-in-use permission.
3. When checking for ProcessRecord.
mAllowBackgroundActivityStartsTokens, it is the caller app's
ProcessRecord should be checked instead of the service's ProcessRecord.

Bug: 182481312
Test: use b/167998084 reproduce steps, use Line app to make a voip call, the
 receiver side screen is unlocked, the receiver side uses bluetooth
headset button to pick up the call, "dumpsys activity -a" shows the FGS
"com.linecorp.voip.core.common.notification.VoipNotificationCommand" has
"allowWhileInUsePermissionInFgs=true" and "isForeground=true".

Change-Id: Ic80aefe4202fe2210881bb8eea24b6e34cb1e7d0
Merged-In: I32a14d675550cd262976bb8e16a48a070387d318
parent 64ab91ef
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -440,4 +440,11 @@ public abstract class ActivityManagerInternal {
     * @return true if exists, false otherwise.
     */
    public abstract boolean isPendingTopUid(int uid);

    public abstract void tempAllowWhileInUsePermissionInFgs(int uid, long duration);

    public abstract boolean isTempAllowlistedForFgsWhileInUse(int uid);

    public abstract boolean canAllowWhileInUsePermissionInFgs(int pid, int uid,
            @NonNull String packageName);
}
+18 −5
Original line number Diff line number Diff line
@@ -4878,18 +4878,21 @@ public final class ActiveServices {
            return true;
        }

        if (r.app != null) {
        if (r != null && r.app != null) {
            ActiveInstrumentation instr = r.app.getActiveInstrumentation();
            if (instr != null && instr.mHasBackgroundActivityStartsPermission) {
                return true;
            }
        }

        final boolean hasAllowBackgroundActivityStartsToken = r.app != null
                ? !r.app.mAllowBackgroundActivityStartsTokens.isEmpty() : false;
        if (hasAllowBackgroundActivityStartsToken) {
        for (int i = mAm.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
            final ProcessRecord pr = mAm.mProcessList.mLruProcesses.get(i);
            if (pr.uid == callingUid) {
                if (!pr.mAllowBackgroundActivityStartsTokens.isEmpty()) {
                    return true;
                }
            }
        }

        if (mAm.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
                == PERMISSION_GRANTED) {
@@ -4907,6 +4910,10 @@ public final class ActiveServices {
            return true;
        }

        if (mAm.mInternal.isTempAllowlistedForFgsWhileInUse(callingUid)) {
            return true;
        }

        final boolean isWhiteListedPackage =
                mWhiteListAllowWhileInUsePermissionInFgs.contains(callingPackage);
        if (isWhiteListedPackage) {
@@ -4920,4 +4927,10 @@ public final class ActiveServices {
        }
        return false;
    }

    boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid,
            String callingPackage) {
        return shouldAllowWhileInUsePermissionInFgsLocked(
                callingPackage, callingPid, callingUid, null, null, false);
    }
}
+25 −0
Original line number Diff line number Diff line
@@ -1261,6 +1261,13 @@ public class ActivityManagerService extends IActivityManager.Stub
    final PendingTempWhitelists mPendingTempWhitelist = new PendingTempWhitelists(this);
    /**
     * List of uids that are allowed to have while-in-use permission when FGS is started from
     * background.
     */
    private final FgsWhileInUseTempAllowList mFgsWhileInUseTempAllowList =
            new FgsWhileInUseTempAllowList();
    /**
     * Information about and control over application operations
     */
@@ -19770,6 +19777,24 @@ public class ActivityManagerService extends IActivityManager.Stub
        public boolean isPendingTopUid(int uid) {
            return mPendingStartActivityUids.isPendingTopUid(uid);
        }
        @Override
        public void tempAllowWhileInUsePermissionInFgs(int uid, long duration) {
            mFgsWhileInUseTempAllowList.add(uid, duration);
        }
        @Override
        public boolean isTempAllowlistedForFgsWhileInUse(int uid) {
            return mFgsWhileInUseTempAllowList.isAllowed(uid);
        }
        @Override
        public boolean canAllowWhileInUsePermissionInFgs(int pid, int uid,
                @NonNull String packageName) {
            synchronized (ActivityManagerService.this) {
                return mServices.canAllowWhileInUsePermissionInFgsLocked(pid, uid, packageName);
            }
        }
    }
    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
+82 −0
Original line number 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 com.android.server.am;

import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;

import android.os.SystemClock;
import android.util.Slog;
import android.util.SparseLongArray;

/**
 * List of uids that are allowed to have while-in-use permission when FGS is started
 * from background.
 */
final class FgsWhileInUseTempAllowList {
    /**
     * This list is supposed to have a small number of entries. If exceeds MAX_SIZE, log a warning
     * message.
     */
    private static final int MAX_SIZE = 100;
    /**
     * The key is the UID, the value is expiration elapse time in ms of this temp-allowed UID.
     */
    private final SparseLongArray mTempAllowListFgs = new SparseLongArray();

    private final Object mLock = new Object();

    void add(int uid, long durationMs) {
        synchronized (mLock) {
            if (durationMs <= 0) {
                Slog.e(TAG_AM, "FgsWhileInUseTempAllowList bad duration:" + durationMs
                        + " uid: " + uid);
                return;
            }
            // The temp allowlist should be a short list with only a few entries in it.
            final int size = mTempAllowListFgs.size();
            if (size > MAX_SIZE) {
                Slog.w(TAG_AM, "FgsWhileInUseTempAllowList length:" + size + " exceeds "
                        + MAX_SIZE);
            }
            final long now = SystemClock.elapsedRealtime();
            for (int index = mTempAllowListFgs.size() - 1; index >= 0; index--) {
                if (mTempAllowListFgs.valueAt(index) < now) {
                    mTempAllowListFgs.removeAt(index);
                }
            }
            final long existingExpirationTime = mTempAllowListFgs.get(uid, -1);
            final long expirationTime = now + durationMs;
            if (existingExpirationTime == -1 || existingExpirationTime < expirationTime) {
                mTempAllowListFgs.put(uid, expirationTime);
            }
        }
    }

    boolean isAllowed(int uid) {
        synchronized (mLock) {
            final int index = mTempAllowListFgs.indexOfKey(uid);
            if (index < 0) {
                return false;
            } else if (mTempAllowListFgs.valueAt(index) < SystemClock.elapsedRealtime()) {
                mTempAllowListFgs.removeAt(index);
                return false;
            } else {
                return true;
            }
        }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -583,6 +583,10 @@ public class AppOpsService extends IAppOpsService.Stub {
                        if (mActivityManagerInternal != null
                                && mActivityManagerInternal.isPendingTopUid(uid)) {
                            return MODE_ALLOWED;
                        } else if (mActivityManagerInternal != null
                                && mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(
                                        uid)) {
                            return MODE_ALLOWED;
                        } else if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
                            return MODE_ALLOWED;
                        } else {
@@ -592,6 +596,10 @@ public class AppOpsService extends IAppOpsService.Stub {
                        if (mActivityManagerInternal != null
                                && mActivityManagerInternal.isPendingTopUid(uid)) {
                            return MODE_ALLOWED;
                        } else if (mActivityManagerInternal != null
                                && mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(
                                        uid)) {
                            return MODE_ALLOWED;
                        } else if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
                            return MODE_ALLOWED;
                        } else {
Loading