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

Commit eba0108f authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Allow apps receiving onMediaButton() callback to start FGS from BG.

Bug: 174699413
Test: manual - verified that the app receiving onMediaButton()
      callback is able to start FGS only when the caller is in a
      state to start FGS.
CTS-Coverage-Bug: 174699413
Change-Id: I2dea43b79aa48fde83c6c3da2ad1454b29d60867
parent 69237805
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.UserHandleAware;
import android.content.Context;

import java.lang.annotation.Retention;
@@ -295,6 +296,11 @@ public class PowerExemptionManager {
     * @hide
     */
    public static final int REASON_SHELL = 316;
    /**
     * Media session callbacks.
     * @hide
     */
    public static final int REASON_MEDIA_SESSION_CALLBACK = 317;

    /**
     * The list of BG-FGS-Launch and temp-allow-list reason code.
@@ -354,6 +360,7 @@ public class PowerExemptionManager {
            REASON_EVENT_SMS,
            REASON_EVENT_MMS,
            REASON_SHELL,
            REASON_MEDIA_SESSION_CALLBACK,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ReasonCode {}
@@ -451,6 +458,7 @@ public class PowerExemptionManager {
     * @param reasonCode one of {@link ReasonCode}, use {@link #REASON_UNKNOWN} if not sure.
     * @param reason a optional human readable reason string, could be null or empty string.
     */
    @UserHandleAware
    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
    public void addToTemporaryAllowList(@NonNull String packageName, long durationMs,
            @ReasonCode int reasonCode, @Nullable String reason) {
@@ -474,6 +482,7 @@ public class PowerExemptionManager {
     *                    used for logging purposes. Could be null or empty string.
     * @return The duration (in milliseconds) that the app is allow-listed for
     */
    @UserHandleAware
    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
    public long addToTemporaryAllowListForEvent(@NonNull String packageName,
            @AllowListEvent int event, @ReasonCode int reasonCode, @Nullable String reason) {
@@ -626,6 +635,8 @@ public class PowerExemptionManager {
                return "EVENT_MMS";
            case REASON_SHELL:
                return "SHELL";
            case REASON_MEDIA_SESSION_CALLBACK:
                return "MEDIA_SESSION_CALLBACK";
            default:
                return "(unknown:" + reasonCode + ")";
        }
+2 −2
Original line number Diff line number Diff line
@@ -2692,7 +2692,7 @@ public class DeviceIdleController extends SystemService
    void addPowerSaveTempAllowlistAppChecked(String packageName, long duration,
            int userId, @ReasonCode int reasonCode, @Nullable String reason)
            throws RemoteException {
        getContext().enforceCallingPermission(
        getContext().enforceCallingOrSelfPermission(
                Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
                "No permission to change device idle whitelist");
        final int callingUid = Binder.getCallingUid();
@@ -2715,7 +2715,7 @@ public class DeviceIdleController extends SystemService

    void removePowerSaveTempAllowlistAppChecked(String packageName, int userId)
            throws RemoteException {
        getContext().enforceCallingPermission(
        getContext().enforceCallingOrSelfPermission(
                Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
                "No permission to change device idle whitelist");
        final int callingUid = Binder.getCallingUid();
+8 −0
Original line number Diff line number Diff line
@@ -88,6 +88,14 @@ package com.android.server {

}

package com.android.server.am {

  public interface ActivityManagerLocal {
    method public boolean canStartForegroundService(int, int, @NonNull String);
  }

}

package com.android.server.role {

  public interface RoleServicePlatformHelper {
+8 −0
Original line number Diff line number Diff line
@@ -35,6 +35,14 @@ package com.android.server {

}

package com.android.server.am {

  public interface ActivityManagerLocal {
    method public boolean canStartForegroundService(int, int, @NonNull String);
  }

}

package com.android.server.role {

  public interface RoleServicePlatformHelper {
+51 −31
Original line number Diff line number Diff line
@@ -5411,16 +5411,28 @@ public final class ActiveServices {
        }
    }

    boolean canStartForegroundServiceLocked(int callingPid, int callingUid, String callingPackage) {
        if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
            return true;
        }
        final @ReasonCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked(
                callingPackage, callingPid, callingUid, null /* serviceRecord */,
                false /* allowBackgroundActivityStarts */);
        final @ReasonCode int allowStartFgs = shouldAllowFgsStartForegroundLocked(
                allowWhileInUse, callingPid, callingUid, callingPackage, null /* targetService */);
        return allowStartFgs != REASON_DENIED;
    }

    /**
     * Should allow while-in-use permissions in FGS or not.
     * A typical BG started FGS is not allowed to have while-in-use permissions.
     * @param callingPackage caller app's package name.
     * @param callingUid caller app's uid.
     * @param r the service to start.
     * @param targetService the service to start.
     * @return {@link ReasonCode}
     */
    private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage,
            int callingPid, int callingUid, ServiceRecord r,
            int callingPid, int callingUid, @Nullable ServiceRecord targetService,
            boolean allowBackgroundActivityStarts) {
        int ret = REASON_DENIED;

@@ -5482,8 +5494,8 @@ public final class ActiveServices {
        }

        if (ret == REASON_DENIED) {
            if (r.app != null) {
                ActiveInstrumentation instr = r.app.getActiveInstrumentation();
            if (targetService != null && targetService.app != null) {
                ActiveInstrumentation instr = targetService.app.getActiveInstrumentation();
                if (instr != null && instr.mHasBackgroundActivityStartsPermission) {
                    ret = REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
                }
@@ -5529,16 +5541,44 @@ public final class ActiveServices {
    private @ReasonCode int shouldAllowFgsStartForegroundLocked(
            @ReasonCode int allowWhileInUse, String callingPackage, int callingPid,
            int callingUid, Intent intent, ServiceRecord r, boolean allowBackgroundActivityStarts) {
        int ret = allowWhileInUse;
        FgsStartTempAllowList.TempFgsAllowListEntry tempAllowListReason =
                r.mInfoTempFgsAllowListReason = mAm.isAllowlistedForFgsStartLOSP(callingUid);
        int ret = shouldAllowFgsStartForegroundLocked(allowWhileInUse, callingPid, callingUid,
                callingPackage, r);

        final StringBuilder sb = new StringBuilder(64);
        final int uidState = mAm.getUidStateLocked(callingUid);
        final String debugInfo =
                "[callingPackage: " + callingPackage
                        + "; callingUid: " + callingUid
                        + "; uidState: " + ProcessList.makeProcStateString(uidState)
                        + "; intent: " + intent
                        + "; code:" + reasonCodeToString(ret)
                        + "; tempAllowListReason:<"
                        + (tempAllowListReason == null ? null :
                                (tempAllowListReason.mReason
                                        + ",reasonCode:"
                                        + reasonCodeToString(tempAllowListReason.mReasonCode)
                                        + ",duration:" + tempAllowListReason.mDuration
                                        + ",callingUid:" + tempAllowListReason.mCallingUid))
                        + ">"
                        + "; targetSdkVersion:" + r.appInfo.targetSdkVersion
                        + "]";
        if (!debugInfo.equals(r.mInfoAllowStartForeground)) {
            r.mLoggedInfoAllowStartForeground = false;
            r.mInfoAllowStartForeground = debugInfo;
        }
        return ret;
    }

    private @ReasonCode int shouldAllowFgsStartForegroundLocked(@ReasonCode int allowWhileInUse,
            int callingPid, int callingUid, String callingPackage,
            @Nullable ServiceRecord targetService) {
        int ret = allowWhileInUse;

        if (ret == REASON_DENIED) {
            final int uidState = mAm.getUidStateLocked(callingUid);
            // Is the calling UID at PROCESS_STATE_TOP or above?
            if (uidState <= PROCESS_STATE_TOP) {
                sb.append("uidState=").append(uidState);
                ret = getReasonCodeFromProcState(uidState);
            }
        }
@@ -5610,8 +5650,10 @@ public final class ActiveServices {

        // NOTE this should always be the last check.
        if (ret == REASON_DENIED) {
            if (isPackageExemptedFromFgsRestriction(r.appInfo.packageName, r.appInfo.uid)
                    || isPackageExemptedFromFgsRestriction(callingPackage, callingUid)) {
            if (isPackageExemptedFromFgsRestriction(callingPackage, callingUid)) {
                ret = REASON_EXEMPTED_PACKAGE;
            } else if (targetService != null && isPackageExemptedFromFgsRestriction(
                    targetService.appInfo.packageName, targetService.appInfo.uid)) {
                ret = REASON_EXEMPTED_PACKAGE;
            }
        }
@@ -5624,28 +5666,6 @@ public final class ActiveServices {
            }
        }

        final String debugInfo =
                "[callingPackage: " + callingPackage
                        + "; callingUid: " + callingUid
                        + "; uidState: " + ProcessList.makeProcStateString(uidState)
                        + "; intent: " + intent
                        + "; code:" + reasonCodeToString(ret)
                        + "; tempAllowListReason:<" +
                        (tempAllowListReason == null ? null :
                                (tempAllowListReason.mReason
                                + ",reasonCode:"
                                + reasonCodeToString(tempAllowListReason.mReasonCode)
                                + ",duration:" + tempAllowListReason.mDuration
                                + ",callingUid:" + tempAllowListReason.mCallingUid))
                        + ">"
                        + "; extra:" + sb.toString()
                        + "; targetSdkVersion:" + r.appInfo.targetSdkVersion
                        + "]";
        if (!debugInfo.equals(r.mInfoAllowStartForeground)) {
            r.mLoggedInfoAllowStartForeground = false;
            r.mInfoAllowStartForeground = debugInfo;
        }

        return ret;
    }

Loading