temporary white list

Introduction to Temporary Whitelist

related constant

Introduction to Temporary Whitelist

The first two temporary whitelists can be exempted from starting the Service in the background, exempting the uid from entering the idle state after 1 minute in the background, etc. The last temporary whitelist can start FGS in the background.

// 由于高优先级消息而暂时允许逃避后台检查的一组应用程序 ID,短信/彩信
@CompositeRWLock({
    
    "this", "mProcLock"})
int[] mDeviceIdleTempAllowlist = new int[0];
// 暂时绕过省电模式的临时白名单,通知
@CompositeRWLock({
    
    "this", "mProcLock"})
final PendingTempAllowlists mPendingTempAllowlist = new PendingTempAllowlists(this);
// 允许从后台启动 FGS 的 临时白名单
@CompositeRWLock({
    
    "this", "mProcLock"})
final FgsTempAllowList<FgsTempAllowListItem> mFgsStartTempAllowList =
            new FgsTempAllowList();
// 当FGS从后台启动时允许具有使用中权限的 uid 列表
private final FgsTempAllowList<String> mFgsWhileInUseTempAllowList =
            new FgsTempAllowList();

Duration of the temporary whitelist

// 当前应用在30s内启动过FGS
private static final int DEFAULT_SERVICE_START_FOREGROUND_TIMEOUT_MS = 30 * 1000;
// locale/timezone/boot/package等广播
private static final int DEFAULT_BOOT_TIME_TEMP_ALLOWLIST_DURATION = 20 * 1000;

Add an application to a temporary allow list for a short period of time for a specific reason. The temporary allowed list is kept separately from the permanent allowed list, and applications are automatically removed from the temporary allowed list after a predetermined time.

// 最大临时白名单豁免时间为5min
private static final long DEFAULT_MAX_TEMP_APP_ALLOWLIST_DURATION_MS = 5 * 60 * 1000L;
// 彩信60s
private static final long DEFAULT_MMS_TEMP_APP_ALLOWLIST_DURATION_MS = 60 * 1000L;
// 短信 20s
private static final long DEFAULT_SMS_TEMP_APP_ALLOWLIST_DURATION_MS = 20 * 1000L;
// 通知30s
private static final long DEFAULT_NOTIFICATION_ALLOWLIST_DURATION_MS = 30 * 1000L;

The reason code of the temporary whitelist

    /**
     * The list of BG-FGS-Launch and temp-allow-list reason code.
     * @hide
     */
    @IntDef(flag = true, prefix = {
    
     "REASON_" }, value = {
    
    
           ......
            // temp and system allow list reasons.
            REASON_GEOFENCING,
            REASON_PUSH_MESSAGING,
            REASON_PUSH_MESSAGING_OVER_QUOTA,
            REASON_ACTIVITY_RECOGNITION,
            REASON_ACCOUNT_TRANSFER,
            REASON_BOOT_COMPLETED,
            REASON_PRE_BOOT_COMPLETED,
            REASON_LOCKED_BOOT_COMPLETED,
            REASON_BLUETOOTH_BROADCAST,
            REASON_TIMEZONE_CHANGED,
            REASON_TIME_CHANGED,
            REASON_LOCALE_CHANGED,
            REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED,
            REASON_REFRESH_SAFETY_SOURCES,
            REASON_SYSTEM_ALLOW_LISTED, 
            REASON_ALARM_MANAGER_ALARM_CLOCK,
            REASON_ALARM_MANAGER_WHILE_IDLE,
            REASON_SERVICE_LAUNCH,
            REASON_KEY_CHAIN,
            REASON_PACKAGE_VERIFIER,
            REASON_SYNC_MANAGER,
            REASON_DOMAIN_VERIFICATION_V1,
            REASON_DOMAIN_VERIFICATION_V2,
            REASON_VPN,
            REASON_NOTIFICATION_SERVICE,
            REASON_PACKAGE_REPLACED,
            REASON_LOCATION_PROVIDER,
            REASON_MEDIA_BUTTON,
            REASON_EVENT_SMS, //
            REASON_EVENT_MMS,
            REASON_SHELL,
            REASON_MEDIA_SESSION_CALLBACK,
            REASON_ROLE_DIALER,
            REASON_ROLE_EMERGENCY,
            REASON_SYSTEM_MODULE,
            REASON_CARRIER_PRIVILEGED_APP,
            REASON_OPT_OUT_REQUESTED,
            REASON_DPO_PROTECTED_APP,
            REASON_DISALLOW_APPS_CONTROL,
            REASON_ACTIVE_DEVICE_ADMIN,
            REASON_MEDIA_NOTIFICATION_TRANSFER,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ReasonCode {
    
    }

Relationship between temporary whitelists

Generally, when adding the mPendingTempAllowlist or mDeviceIdleTempAllowlist whitelist, the mFgsStartTempAllowList whitelist will also be added according to whether the type is TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED.

// 允许临时白名单行为,并允许前台服务从后台启动。
public static final int TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0;

mPendingTempAllowlist & mFgsStartTempAllowList

When the tempAllowlistUidLocked method is called to set the temporary whitelist, there may be scenarios where the device is added to the mPendingTempAllowlist and mFgsStartTempAllowList whitelists at the same time.

    @GuardedBy("this")
    void tempAllowlistUidLocked(int targetUid, long duration, @ReasonCode int reasonCode,
            String reason, @TempAllowListType int type, int callingUid) {
    
    
        synchronized (mProcLock) {
    
    
          ......
            // 添加到临时Pending白名单中
            mPendingTempAllowlist.put(targetUid,
                    new PendingTempAllowlist(targetUid, duration, reasonCode, reason, type,
                            callingUid));
            // 设置当前uid的curAllowlist
            setUidTempAllowlistStateLSP(targetUid, true);
            mUiHandler.obtainMessage(PUSH_TEMP_ALLOWLIST_UI_MSG).sendToTarget();
        	// 添加到允许从后台启动 FGS 的 临时白名单
            if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
    
    
                mFgsStartTempAllowList.add(targetUid, duration,
                        new FgsTempAllowListItem(duration, reasonCode, reason, callingUid));
            }
        }
    }

Find the calling place of tempAllowlistUidLocked as follows, mainly in three scenarios: broadcast, Service, PendingIntent notification.
insert image description here

mDeviceIdleTempAllowlist & mFgsStartTempAllowList

Adding a whitelist of type TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED will trigger the update of mDeviceIdleTempAllowlist.

@Override
public void updateDeviceIdleTempAllowlist(@Nullable int[] appids, int changingUid,
        boolean adding, long durationMs, @TempAllowListType int type,
        @ReasonCode int reasonCode, @Nullable String reason, int callingUid) {
    
    
    synchronized (ActivityManagerService.this) {
    
    
        synchronized (mProcLock) {
    
    
            if (appids != null) {
    
    
                // 更新device idle临时白名单
                mDeviceIdleTempAllowlist = appids;
            }
            if (adding) {
    
    
                if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) {
    
    
                    // 更新后台启动FGS的临时白名单
                    mFgsStartTempAllowList.add(changingUid, durationMs,
                            new FgsTempAllowListItem(durationMs, reasonCode, reason,
                            callingUid));
                }
            } else {
    
    
                mFgsStartTempAllowList.removeUid(changingUid);
            }
            // 设置当前uid的curAllowListed为true,避免uid处于idle状态
            setAppIdTempAllowlistStateLSP(changingUid, adding);
        }
    }
}

The calling scenarios involve a wide range and are not listed for now.

Summary of common adding scenarios

Reason for joining duration Reason Code
fg-service-launch 30s REASON_SERVICE_LAUNCH
receive special broadcasts 20s REASON_LOCALE_CHANGED
REASON_TIMEZONE_CHANGED
REASON_TIME_CHANGED
REASON_BOOT_COMPLETED
REASON_PRE_BOOT_COMPLETED
REASON_LOCKED_BOOT_COMPLETED
REASON_PACKAGE_REPLACED
REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
Bluetooth 10s REASON_BLUETOOTH_BROADCAST
position 10s REASON_LOCATION_PROVIDER
NotificationManagerService 30s REASON_NOTIFICATION_SERVICE
Geofence 30s REASON_GEOFENCING
push app 60s REASON_PUSH_MESSAGING

Temporary whitelist for starting FGS in the background

The current application has started FGS within 30s

if (r.fgRequired) {
    
    
    // 30s,调用了如上面说的AMS的tempAllowlistUidLocked
    mAm.tempAllowlistUidLocked(r.appInfo.uid,
            mAm.mConstants.mServiceStartForegroundTimeoutMs, REASON_SERVICE_LAUNCH,
            "fg-service-launch",
            TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
            r.mRecentCallingUid);
}

The application receives the PendingIntent notification from the system

Users perform actions on UI elements related to your application. For example, they might interact with bubbles, notifications, widgets, or activities.

        // temporarily allow apps to perform extra work when their pending intents are launched
        if (notification.allPendingIntents != null) {
    
    
            final int intentCount = notification.allPendingIntents.size();
            if (intentCount > 0) {
    
    
                // 30s
                final long duration = LocalServices.getService(
                        DeviceIdleInternal.class).getNotificationAllowlistDuration();
                for (int i = 0; i < intentCount; i++) {
    
    
                    PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
                    if (pendingIntent != null) {
    
    
                        // 设置duration
                        mAmi.setPendingIntentAllowlistDuration(pendingIntent.getTarget(),
                                ALLOWLIST_TOKEN, duration,
                                // FGS 启动
                                TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                                REASON_NOTIFICATION_SERVICE,
                                "NotificationManagerService");
                    }
                }
            }
        }

Set the Duration first, and then set the temporary whitelist when sending

    // allowlistToken为target
    // 这里的reason为NotificationManagerService
    // reasonCode为REASON_NOTIFICATION_SERVICE
    // type为TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED
    // duration为30s
	void setAllowlistDurationLocked(IBinder allowlistToken, long duration, int type,
            @ReasonCode int reasonCode, @Nullable String reason) {
    
     
        if (duration > 0) {
    
    
            if (mAllowlistDuration == null) {
    
    
                mAllowlistDuration = new ArrayMap<>();
            }
            mAllowlistDuration.put(allowlistToken,
                    new TempAllowListDuration(duration, type, reasonCode, reason));
        } else if (mAllowlistDuration != null) {
    
    
            mAllowlistDuration.remove(allowlistToken);
            if (mAllowlistDuration.size() <= 0) {
    
    
                mAllowlistDuration = null;
            }
        }
        this.stringName = null;
    }

When PendingIntent is sent, it will pass the verification and notify AMS to set a temporary whitelist

    public int sendInner(int code, Intent intent, String resolvedType, IBinder allowlistToken,
            IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo,
            String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) {
    
    
        .......
        synchronized (controller.mLock) {
    
    
           ......
            // 如果在通知入队时已经设置了duration
            if (mAllowlistDuration != null) {
    
    
                duration = mAllowlistDuration.get(allowlistToken);
            }
            .......
        }
       ......
        try {
    
    
            // 调用AMS接口tempAllowlistForPendingIntent设置临时白名单
            if (duration != null) {
    
    
               .......
                controller.mAmInternal.tempAllowlistForPendingIntent(callingPid, callingUid,
                        uid, duration.duration, duration.type, duration.reasonCode, tag.toString());
            } 
          ....

App receives special broadcast in broadcast receiver

Sets the duration for which the system should temporarily place the application in the battery whitelist, specifying the temporary whitelist type when this broadcast is delivered to it.

The broadcasts listed below are not all. There are still some broadcasts such as boot, alarm, media, package, and bluetooth that are not listed one by one. If you encounter specific problems, you can analyze them in detail.

	// 要求应用拥有以下三个权限中的其中一个:
	@RequiresPermission(anyOf = {
    
    android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
            android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
            android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND})
    public void setTemporaryAppAllowlist(long duration, @TempAllowListType int type,
            @ReasonCode int reasonCode, @Nullable String reason) {
    
    
        mTemporaryAppAllowlistDuration = duration;
        mTemporaryAppAllowlistType = type;
        mTemporaryAppAllowlistReasonCode = reasonCode;
        mTemporaryAppAllowlistReason = reason;

        if (!isTemporaryAppAllowlistSet()) {
    
    
            resetTemporaryAppAllowlist();
        }
    }
    void maybeScheduleTempAllowlistLocked(int uid, BroadcastRecord r,
            @Nullable BroadcastOptions brOptions) {
    
    
        if (brOptions == null || brOptions.getTemporaryAppAllowlistDuration() <= 0) {
    
    
            return;
        }
        long duration = brOptions.getTemporaryAppAllowlistDuration();
        final @TempAllowListType int type = brOptions.getTemporaryAppAllowlistType();
        final @ReasonCode int reasonCode = brOptions.getTemporaryAppAllowlistReasonCode();
        final String reason = brOptions.getTemporaryAppAllowlistReason();
    	.......
        mService.tempAllowlistUidLocked(uid, duration, reasonCode, b.toString(), type,r.callingUid);
    }

When to add to the temporary whitelist: trigger an update or add before distributing to the app
insert image description here

接收ACTION_LOCALE_CHANGED/ACTION_TIMEZONE_CHANGED/ACTION_TIME_CHANGED

Your app receives ACTION_TIMEZONE_CHANGED , ACTION_TIME_CHANGED , or ACTION_LOCALE_CHANGED intent actions in a broadcast receiver.

@Override
public void broadcastGlobalConfigurationChanged(int changes, boolean initLocale) {
    
    
    synchronized (ActivityManagerService.this) {
    
    
        ......
        if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
    
    
            intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
        	.......
            final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
            // 20s
            bOptions.setTemporaryAppAllowlist(mInternal.getBootTimeTempAllowListDuration(),
                    TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                    PowerExemptionManager.REASON_LOCALE_CHANGED, "");
                    ......
        }
    void setTimeZoneImpl(String tz) {
    
    
    	......
        if (timeZoneWasChanged) {
    
    
            .....
            Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
            .....
            mOptsTimeBroadcast.setTemporaryAppAllowlist(
                    mActivityManagerInternal.getBootTimeTempAllowListDuration(),
                    TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                    PowerExemptionManager.REASON_TIMEZONE_CHANGED, "");
            getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
                    null /* receiverPermission */, mOptsTimeBroadcast.toBundle());
        }
    }
Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
                        ......
mOptsTimeBroadcast.setTemporaryAppAllowlist(
            mActivityManagerInternal.getBootTimeTempAllowListDuration(),
            TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
        	PowerExemptionManager.REASON_TIME_CHANGED, "");

Receive broadcasts such as BOOT_COMPLETED/PACKAGE_REPLACED

After the device reboots and receives an ACTION_BOOT_COMPLETED, ACTION_PRE_BOOT_COMPLETED, ACTION_LOCKED_BOOT_COMPLETED, or ACTION_MY_PACKAGE_REPLACED intent action in the broadcast receiver.

final BroadcastOptions bOptions = getTemporaryAppAllowlistBroadcastOptions(
                    REASON_LOCKED_BOOT_COMPLETED);
    public @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
            @PowerExemptionManager.ReasonCode int reasonCode) {
    
    
        long duration = 10_000;
        if (mAmInternal != null) {
    
    
            duration = mAmInternal.getBootTimeTempAllowListDuration();
        }
        final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
        bOptions.setTemporaryAppAllowlist(duration,
                TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                reasonCode, "");
        return bOptions;
    }
// 10s
mPm.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
        null /*package*/, null /*extras*/, 0 /*flags*/,
        packageName /*targetPackage*/,
        null /*finishedReceiver*/, updateUserIds, instantUserIds,
        null /*broadcastAllowList*/,
        mBroadcastHelper.getTemporaryAppAllowlistBroadcastOptions(
            REASON_PACKAGE_REPLACED).toBundle());

Receive ACTION_BLE_STATE_CHANGED Bluetooth broadcast

Your app receives Bluetooth broadcasts that require the BLUETOOTH_CONNECT or BLUETOOTH_SCAN permission.

    private void sendBleStateChanged(int prevState, int newState) {
    
    
       ......
        // Send broadcast message to everyone else
        Intent intent = new Intent(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, getTempAllowlistBroadcastOptions());
    }
    static @NonNull Bundle getTempAllowlistBroadcastOptions() {
    
    
        final long duration = 10_000;
        final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
        bOptions.setTemporaryAppAllowlist(duration,
                TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, "");
        return bOptions.toBundle();
    }

App receives location change event

        @Override
        public void deliverOnLocationChanged(LocationResult locationResult,
                @Nullable IRemoteCallback onCompleteCallback)
                throws PendingIntent.CanceledException {
    
    
            BroadcastOptions options = BroadcastOptions.makeBasic();
            options.setDontSendToRestrictedApps(true);
            // allows apps to start a fg service in response to a location PI
            options.setTemporaryAppAllowlist(TEMPORARY_APP_ALLOWLIST_DURATION_MS,
                    TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                    REASON_LOCATION_PROVIDER,
                    "");

            Intent intent = new Intent().putExtra(KEY_LOCATION_CHANGED,
                    locationResult.getLastLocation());
        	......
            PendingIntentSender.send(mPendingIntent, mContext, intent, callback,
                    options.toBundle());
        }

App receives event with geofence

Your app receives events related to geofence or activity recognition transitions.

PowerExemptionManager powerEM = context.getSystemService(PowerExemptionManager.class);
powerEM.addToTemporaryAllowList(packageName, PowerExemptionManager.REASON_GEOFENCING, "", Const.TEMP_ALLOW_DURATION_MS);
    void addPowerSaveTempAllowlistAppChecked(String packageName, long duration,
            int userId, @ReasonCode int reasonCode, @Nullable String reason)
            throws RemoteException {
    
    
        ......
        final long token = Binder.clearCallingIdentity();
        try {
    
    
            @TempAllowListType int type = getTempAllowListType(reasonCode,
                    TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
            if (type != TEMPORARY_ALLOW_LIST_TYPE_NONE) {
    
    
                addPowerSaveTempAllowlistAppInternal(callingUid,
                        packageName, duration, type, userId, true, reasonCode, reason);
            }
        } finally {
    
    
            Binder.restoreCallingIdentity(token);
        }
    }

Application is Push App

Your app receives high-priority messages using Firebase Cloud Messaging.

mAmService.tempAllowlistUidLocked(record.getUid(),
        PUSH_SERVICE_WHITELIST_TIMEOUT,
        PowerExemptionManager.REASON_PUSH_MESSAGING,
    	"push-service-launch",
        PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
        callingUid);

…More

Device Idle Temporary Whitelist

SMS/MMS

    @UserHandleAware
    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
    public long addToTemporaryAllowListForEvent(@NonNull String packageName,
            @ReasonCode int reasonCode, @Nullable String reason, @AllowListEvent int event) {
    
    
        try {
    
    
            switch (event) {
    
    
                case EVENT_MMS:
                    return mService.addPowerSaveTempWhitelistAppForMms(
                            packageName, mContext.getUserId(), reasonCode, reason);
                case EVENT_SMS:
                    return mService.addPowerSaveTempWhitelistAppForSms(
                            packageName, mContext.getUserId(), reasonCode, reason);
                case EVENT_UNSPECIFIED:
                default:
                    return mService.whitelistAppTemporarily(
                            packageName, mContext.getUserId(), reasonCode, reason);
            }
        } catch (RemoteException e) {
    
    
            throw e.rethrowFromSystemServer();
        }
    }

It is mainly to call power-related interface settings. The specific setting process is as follows: sequence diagram
insert image description here

Geofence

For specific calls, see Application Received and Geofence Events

    @UserHandleAware
    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
    public void addToTemporaryAllowList(@NonNull String packageName, @ReasonCode int reasonCode,
            @Nullable String reason, long durationMs) {
    
    
        try {
    
    
            mService.addPowerSaveTempWhitelistApp(packageName, durationMs, mContext.getUserId(),
                    reasonCode, reason);
        } catch (RemoteException e) {
    
    
            throw e.rethrowFromSystemServer();
        }
    }

Whether the current Uid is in the whitelist

Whether the Uid is in the whitelist

Whether the uid is in the whitelist affects whether the current uid will be idle; idle apps will have background service restrictions.

// procState >= PROCESS_STATE_TRANSIENT_BACKGROUND 8
if (ActivityManager.isProcStateBackground(uidRec.getCurProcState())
        && !uidRec.isCurAllowListed()) {
    
    
    // UID 现在在后台(不在临时许可名单上)。 它之前是否在前台(或在临时许可名单上)?
    if (!ActivityManager.isProcStateBackground(uidRec.getSetProcState())
        || uidRec.isSetAllowListed()) {
    
    
        // 这里传入的elapsedRealtime而不是uptimeMillis,谷歌代码曾出过问题,
        uidRec.setLastBackgroundTime(nowElapsed);
        if (!mService.mHandler.hasMessages(IDLE_UIDS_MSG)) {
    
    
            // post 1min后的消息到handler中去执行idle操作
            mService.mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
                    mConstants.BACKGROUND_SETTLE_TIME);
        }
    }
    if (uidRec.isIdle() && !uidRec.isSetIdle()) {
    
    
        uidChange |= UidRecord.CHANGE_IDLE;
        becameIdle.add(uidRec);
    }

Whether the setting is in the whitelist

There are three ways to set whether uid is in the whitelist:
insert image description here

setAppIdTempAllowlistStateLSP

When setting the list of mDeviceIdleTempAllowlist, the curAllowListed of the current uid will be updated. For specific calls, see mDeviceIdleTempAllowlist
insert image description here

    @GuardedBy({
    
    "mService", "mProcLock"})
    void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
    
    
        boolean changed = false;
        for (int i = mActiveUids.size() - 1; i >= 0; i--) {
    
    
            final UidRecord uidRec = mActiveUids.valueAt(i);
            if (uidRec.getUid() == uid && uidRec.isCurAllowListed() != onAllowlist) {
    
    
                // 设置当前uid的curAllowListed,如果是加入白名单,这里为true
                // 可用作判断当前uid的状态是否为idle
                uidRec.setCurAllowListed(onAllowlist);
                changed = true;
            }
        }
        if (changed) {
    
    
            updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
        }
    }

setUidTempAllowlistStateLSP

When setting the mPendingTempAllowlist whitelist, the whitelist attribute of the current uid will also be set to true; see mPendingTempAllowlist for specific calls
insert image description here

    @GuardedBy({
    
    "mService", "mProcLock"})
    void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
    
    
        boolean changed = false;
        final UidRecord uidRec = mActiveUids.get(uid);
        if (uidRec != null && uidRec.isCurAllowListed() != onAllowlist) {
    
    
            uidRec.setCurAllowListed(onAllowlist);
            updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
        }
    }

addProcessNameLocked

Similarly, if the current uid exists in the mDeviceIdleTempAllowlist or mPendingTempAllowlist whitelist when creating the adding process, directly set curAllowListed of the current uid to true.

if (Arrays.binarySearch(mService.mDeviceIdleTempAllowlist,
            UserHandle.getAppId(proc.uid)) >= 0
        || mService.mPendingTempAllowlist.indexOfKey(proc.uid) >= 0) {
    
    
    uidRec.setCurAllowListed(true);
    uidRec.setSetAllowListed(true);
}

Guess you like

Origin blog.csdn.net/xiaoyantan/article/details/128529908