临时白名单

news2025/1/15 12:52:00

临时白名单介绍

相关常量

临时白名单列表介绍

前两个临时白名单可以豁免后台启动Service、豁免uid后台1min后进入idle状态等,最后一个临时白名单可以后台启动FGS。

// 由于高优先级消息而暂时允许逃避后台检查的一组应用程序 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

// 当前应用在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;

出于特定原因在短时间内将应用程序添加到临时允许列表。 临时允许列表与永久允许列表分开保存,应用程序会在预定时间后自动从临时允许列表中删除。

// 最大临时白名单豁免时间为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;

临时白名单的reason code

    /**
     * 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 {}

临时白名单之间关系

一般添加mPendingTempAllowlist或mDeviceIdleTempAllowlist白名单时也会根据type是否是TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED来添加mFgsStartTempAllowList白名单。

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

mPendingTempAllowlist & mFgsStartTempAllowList

调用tempAllowlistUidLocked方法设置临时白名单时,会存在同时添加到mPendingTempAllowlist和 mFgsStartTempAllowList白名单的场景。

    @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));
            }
        }
    }

查找tempAllowlistUidLocked的调用地方如下,主要是三个场景:广播、Service、PendingIntent通知。
在这里插入图片描述

mDeviceIdleTempAllowlist & mFgsStartTempAllowList

添加TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED类型的白名单会触发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);
        }
    }
}

调用场景涉及范围较大,暂不列出。

常见添加场景总结

加入原因持续时间原因Code
fg-service-launch30sREASON_SERVICE_LAUNCH
接收特殊广播20sREASON_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
蓝牙10sREASON_BLUETOOTH_BROADCAST
定位10sREASON_LOCATION_PROVIDER
NotificationManagerService30sREASON_NOTIFICATION_SERVICE
地理围栏30sREASON_GEOFENCING
推送app60sREASON_PUSH_MESSAGING

后台启动FGS的临时白名单

当前应用在30s内启动过FGS

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);
}

应用收到系统的 PendingIntent 通知

用户对与您的应用程序相关的 UI 元素执行操作。 例如,他们可能会与气泡、通知、小部件或活动进行交互。

        // 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");
                    }
                }
            }
        }

先设置Duration,然后在send时去设置临时白名单

    // 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;
    }

PendingIntent发送时会通过校验,通知AMS设置临时白名单

    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());
            } 
          ....

应用在广播接收器中接收特殊广播

设置一个持续时间,系统应在该持续时间内将应用程序临时放置在电池白名单中,在此广播被传送到它时,指定临时白名单类型。

以下列举的广播并不是全部,还有一些boot、alarm、media、package、bluetooth等广播没有一一列举出来,遇到具体问题再具体分析即可。

	// 要求应用拥有以下三个权限中的其中一个:
	@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);
    }

添加到临时白名单的时机:分发给app之前触发更新或添加
在这里插入图片描述

接收ACTION_LOCALE_CHANGED/ACTION_TIMEZONE_CHANGED/ACTION_TIME_CHANGED

您的应用在广播接收器中接收 ACTION_TIMEZONE_CHANGED、ACTION_TIME_CHANGED 或 ACTION_LOCALE_CHANGED 意图操作。

@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, "");

接收BOOT_COMPLETED/PACKAGE_REPLACED等广播

设备重启并在广播接收器中接收到 ACTION_BOOT_COMPLETED、ACTION_PRE_BOOT_COMPLETED、ACTION_LOCKED_BOOT_COMPLETED 或 ACTION_MY_PACKAGE_REPLACED 意图操作后。

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());

接收ACTION_BLE_STATE_CHANGED蓝牙广播

您的应用程序接收需要 BLUETOOTH_CONNECT 或 BLUETOOTH_SCAN 权限的蓝牙广播。

    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();
    }

应用接收位置改变事件

        @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());
        }

应用收到与地理围栏事件

您的应用收到与地理围栏或活动识别转换相关的事件。

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);
        }
    }

应用是推送App

您的应用使用 Firebase 云消息传递接收高优先级消息。

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

设备空闲临时白名单

短信/彩信

    @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();
        }
    }

主要是调用power相关的接口设置,具体设置流程如下时序图
在这里插入图片描述

地理围栏

具体调用见 应用收到与地理围栏事件

    @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();
        }
    }

当前Uid是否处于白名单

Uid是否处于白名单作用

uid是否处于白名单影响当前uid是否会被idle;idle的app会有后台Service限制。

// 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);
    }

设置是否处于白名单

设置uid是否处于白名单有如下三处:
在这里插入图片描述

setAppIdTempAllowlistStateLSP

设置mDeviceIdleTempAllowlist名单的时候会更新当前uid的curAllowListed ,具体调用见mDeviceIdleTempAllowlist
在这里插入图片描述

    @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

设置mPendingTempAllowlist白名单时也会设置当前uid的白名单属性为true;具体调用见 mPendingTempAllowlist
在这里插入图片描述

    @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

同样如果创建添加进程的时候,当前uid存在于mDeviceIdleTempAllowlist或者mPendingTempAllowlist白名单中,直接设置当前uid的curAllowListed为true。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/145433.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Vue路由】路由守卫、生命周期钩子、路由器工作模式

文章目录生命周期钩子案例实现总结路由守卫全局路由守卫独享守卫组件内守卫总结路由器的两种工作模式总结生命周期钩子 我们在News组件列表中的第一行加一个渐变文字。同时原来的路由缓存功能也要保存。 案例分析&#xff1a; 我们实现这个渐变的效果&#xff0c;是使用周期定…

Go select底层原理

在对Channel的读写方式上&#xff0c;除了我们通用的读 i <- ch, i, ok <- ch&#xff0c;写 ch <- 1 这种阻塞访问方式&#xff0c;还有select关键字提供的非阻塞访问方式。 在日常开发中&#xff0c;select语句还是会经常用到的。可能是channel普通读写的使用频率比…

基于Node.js和vue的博客系统的设计与实现

摘要随着互联网技术的高速发展&#xff0c;人们生活的各方面都受到互联网技术的影响。现在人们可以通过互联网技术就能实现不出家门就可以在线发布博客文章&#xff0c;简单、快捷的方便了人们的日常生活。同样的&#xff0c;在人们的工作生活中&#xff0c;也需要互联网技术来…

【Java寒假打卡】Java基础-日期类对象

【Java寒假打卡】Java基础-日期类对象Date概述Date类常用成员方法SimpleDateFormat案例:秒杀活动案例&#xff1a;在当前时间加上一天时间JDK8新增日期类获取时间中的一个值LocalDateTime转换方法LocalDateTime格式化和解析LocalDateTime 增加或者减少时间的方法修改时间的方法…

【JAVA程序设计】(C00099)基于SpringBoot的外卖订餐小程序(原生开发)

基于SpringBoot的外卖订餐小程序&#xff08;原生开发&#xff09;项目简介项目获取开发环境项目技术运行截图项目简介 基于SpringBootvue开发的原生外卖点餐微信小程序&#xff0c;包括用户小程序登录以及网页端的商家登录。本系统分为三个权限&#xff1a;商家、用户和游客&…

第七章.机器学习 Scikit-Learn—最小二乘法回归,岭回归,支持向量机,K_means聚类算法

第七章.机器学习 Scikit-Learn 7.1 Scikit-Learn简介 Scikit-Learn简称(SKlearn)是Python的第三方模块&#xff0c;是机器学习领域当中知名的Python模块之一&#xff0c;对常用的机器学习算法进行了封装&#xff0c;包括回归(Regression)&#xff0c;降维(Dimensionality Redu…

地质灾害监测预警系统构成,功能,监测设备介绍

平升电子地质灾害监测预警系统&#xff0c;应用平升物联网遥测终端机、专业测量仪器和传感设备、预警广播设备、地质灾害监测预警平台&#xff0c;基于4G/5G/NB-IoT/LoRa/光纤/北斗卫星通信网络&#xff0c;实时在线监测地质灾害隐患点的地表位移、地表裂缝、深部位移、降雨量、…

Simulink-过零检测与代数环

过零检测过零检测即通过Simulink为模块注册若干过零函数&#xff0c;当模块变化趋势剧烈时&#xff0c;过零函数将会发生符号变化。每个采样点仿真结束时&#xff0c;Simulink检测过零函数是否有符号变化&#xff0c;如果检测到过零点&#xff0c;则Simulink将在前一个采样点和…

院内导航方案怎么样,低成本的智慧医院室内导航一站式解决方案

很多智慧医院的方案里都提到了院内导航&#xff0c;它俨然已经成为智慧医院套餐中的“招牌菜”&#xff0c;甚至被打上了“导航神器”的绰号&#xff0c;其中电子地图作为大家最喜闻乐见的高效应用形式&#xff0c;可以高效的为病患提供导医服务&#xff0c;实现院内导航功能&a…

集群多机ROS通信中间件:swarm_ros_bridge

最近写了一个无线网络环境下&#xff08;比如WIFI&#xff09;多机ROS通信的项目swarm_ros_bridge&#xff1a; https://gitee.com/shu-peixuan/swarm_ros_bridge A lightweight middle interface that enables specified ROS message transmission among swarm robots throu…

国内出海企业常见的跨境网络问题分析及解决方案

经济全球化趋势发展得如火如荼&#xff0c;越来越多的中国企业走出国门&#xff0c;兴起包括跨境电商、虚拟商品、游戏出海等新贸易形式。但在业务开拓过程中&#xff0c;由于远距离传输的特殊性&#xff0c;出海企业经常面临网络传输慢、不稳定、延迟、掉线等网络问题&#xf…

0基础如何开始学习计算机知识?

一、计算机的基本操作 计算机中只有文件和文件夹 计算机中&#xff0c;只有两样东西&#xff0c;文件和文件夹。 文件夹&#xff1a;本身不存储数据内容。文件夹是用来组织和管理文件的。 文件&#xff1a; 所有的txt文本文档&#xff0c;音乐&#xff0c;视频&#xff0c;图…

2022年国外LEAD收入情况

欢迎关注勤于奋每天12点准时更新国外LEAD相关技术这个收入情况&#xff0c;最喜欢关心&#xff0c;最喜欢看的人应该是新手和观望的人最想知道的&#xff0c;LEAD收入只要操作了&#xff0c;赚钱肯定是没问题&#xff0c;我一直这样说&#xff0c;而且我公众号叫勤于奋&#xf…

【Spring(四)】万字详解bean的实例化

文章目录前言1.bean实例化1.1 bean的基础配置1.2 bean的实例化-构造方法1.3 bean的实例化-静态工厂1.4 bean的实例化-实例工厂与FactoryBean总结前言 在上篇文章&#xff0c;我们已经完成了入门案例的学习&#xff0c;在入门案例中&#xff0c;我们讲了三块东西&#xff0c;首先…

《Kotlin核心编程》笔记:函数和Lambda表达式

高阶函数和lambda表达式 函数式语言⼀个典型的特征就在于函数是头等公民——我们不仅可以像类⼀样在顶层直接定义⼀个函数&#xff0c;也可以在⼀个函数内部定义⼀个局部函数&#xff0c;如下所示&#xff1a;所谓的高阶函数&#xff0c;你可以把它理解成“ 以其他函数作为参数…

Debian10,docker单机安装ThingsBoard-3.3.2

1.编译项目源码 源代码编译ThingsBoard-3.3.2 2.环境准备 修改ssh登录配置 sudo vi /etc/ssh/sshd_config 打开密码登录和root用户登录3.安装docker 更新apt sudo apt update安装必备软件 sudo apt install apt-transport-https ca-certificates curl gnupg2 software-p…

SpringBoot异步方法(官方案例)

在线文档项目结构 1.源码克隆&#xff1a;git clone https://github.com/spring-guides/gs-async-method.git 2.包含两个项目initial和complete&#xff0c;initial可以根据文档练习完善&#xff0c;complete是完整项目 3.功能描述&#xff1a;构建查找服务&#xff0c;异步查询…

Linux搭建Docker版FTP,命令与Dockerfile两种方式以及容器编码解决

Linux搭建Docker版FTP&#xff0c;命令与Dockerfile两种方式以及容器编码解决一、Linux搭建Docker版FTP二、修改 Docker 容器内部 locale 系统编码最终待实现效果&#xff0c;这个方式容器内部编码并未永久改变三、编写Dockerfile方式加载带UTF-8编码环境的镜像3.1Dockerfile构…

【LINUX权限】

目录&#xff1a;前言一、shell二、权限&#xff08;一&#xff09;文件权限&#xff08;二&#xff09;权限相关指令chmod&#xff08;修改权限&#xff09;su 、sudo&#xff08;提权&#xff09;root提权chown 、chgrpumask&#xff08;掩码&#xff09;file&#xff08;三&…

性能测试工具 Lmbench 的使用方法以及解析运行结果

1. Lmbench 简介 Lmbench 是一款简易可以移植的内存测试工具&#xff0c;其主要功能有&#xff0c;带宽测评&#xff08;读取缓存文件、拷贝内存、读/写内存、管道、TCP&#xff09;&#xff0c;延时测评&#xff08;上下文切换、网络、文件系统的建立和删除、进程创建、信号处…