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

Commit 69b56d9e authored by Xin Guan's avatar Xin Guan
Browse files

Modify usagestats event processing thread

Use a dedicated thread with default priority to handle
the usage stats event processing.

Bug: 303798680
Bug: 302675504
Test: atest CtsUsageStatsTestCases
Test: atest FrameworksCoreTests:android.app.usage.*
Change-Id: I0bdd65d5ef1ed61ab5b8fdf4f1a3a257f1b37111
parent 119edfa1
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -13,3 +13,11 @@ flag {
    description: "Feature flag for the new REPORT_USAGE_STATS permission."
    bug: "296056771"
}

flag {
    name: "use_dedicated_handler_thread"
    namespace: "backstage_power"
    description: "Flag to use a dedicated thread for usage event process"
    is_fixed_read_only: true
    bug: "299336442"
}
+64 −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.usage;

import android.os.Looper;
import android.os.Trace;

import com.android.internal.annotations.GuardedBy;
import com.android.server.ServiceThread;

/**
 * Shared singleton default priority thread for usage stats message handling.
 */
public class UsageStatsHandlerThread extends ServiceThread {
    private static final long SLOW_DISPATCH_THRESHOLD_MS = 10_000;
    private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000;

    private static final Object sLock = new Object();

    @GuardedBy("sLock")
    private static UsageStatsHandlerThread sInstance;

    private UsageStatsHandlerThread() {
        super("android.usagestats", android.os.Process.THREAD_PRIORITY_DEFAULT,
                /* allowIo= */ true);
    }

    @GuardedBy("sLock")
    private static void ensureThreadLocked() {
        if (sInstance != null) {
            return;
        }

        sInstance = new UsageStatsHandlerThread();
        sInstance.start();
        final Looper looper = sInstance.getLooper();
        looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
        looper.setSlowLogThresholdMs(
                SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
    }

    /**
     * Obtain a singleton instance of the UsageStatsHandlerThread.
     */
    public static UsageStatsHandlerThread get() {
        synchronized (sLock) {
            ensureThreadLocked();
            return sInstance;
        }
    }
}
+20 −7
Original line number Diff line number Diff line
@@ -202,6 +202,7 @@ public class UsageStatsService extends SystemService implements
    static final int MSG_HANDLE_LAUNCH_TIME_ON_USER_UNLOCK = 8;
    static final int MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED = 9;
    static final int MSG_UID_REMOVED = 10;
    static final int MSG_USER_STARTED = 11;

    private final Object mLock = new Object();
    private Handler mHandler;
@@ -334,7 +335,7 @@ public class UsageStatsService extends SystemService implements
        mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
        mPackageManager = getContext().getPackageManager();
        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
        mHandler = new H(BackgroundThread.get().getLooper());
        mHandler = getUsageEventProcessingHandler();
        mIoHandler = new Handler(IoThread.get().getLooper(), mIoHandlerCallback);

        mAppStandby = mInjector.getAppStandbyController(getContext());
@@ -380,10 +381,12 @@ public class UsageStatsService extends SystemService implements

        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
        filter.addAction(Intent.ACTION_USER_STARTED);
        getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL,
                filter, null, /* Handler scheduler */ null);
        getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
                null, /* scheduler= */ Flags.useDedicatedHandlerThread() ? mHandler : null);

        getContext().registerReceiverAsUser(new UidRemovedReceiver(), UserHandle.ALL,
                new IntentFilter(ACTION_UID_REMOVED), null, /* Handler scheduler */ null);
                new IntentFilter(ACTION_UID_REMOVED), null,
                /* scheduler= */ Flags.useDedicatedHandlerThread() ? mHandler : null);

        mRealTimeSnapshot = SystemClock.elapsedRealtime();
        mSystemTimeSnapshot = System.currentTimeMillis();
@@ -471,6 +474,14 @@ public class UsageStatsService extends SystemService implements
        }
    }

    private Handler getUsageEventProcessingHandler() {
        if (Flags.useDedicatedHandlerThread()) {
            return new H(UsageStatsHandlerThread.get().getLooper());
        } else {
            return new H(BackgroundThread.get().getLooper());
        }
    }

    private void onUserUnlocked(int userId) {
        // fetch the installed packages outside the lock so it doesn't block package manager.
        final HashMap<String, Long> installedPackages = getInstalledPackages(userId);
@@ -618,7 +629,7 @@ public class UsageStatsService extends SystemService implements
                }
            } else if (Intent.ACTION_USER_STARTED.equals(action)) {
                if (userId >= 0) {
                    mAppStandby.postCheckIdleStates(userId);
                    mHandler.obtainMessage(MSG_USER_STARTED, userId, 0).sendToTarget();
                }
            }
        }
@@ -1554,8 +1565,7 @@ public class UsageStatsService extends SystemService implements
        synchronized (mLaunchTimeAlarmQueues) {
            LaunchTimeAlarmQueue alarmQueue = mLaunchTimeAlarmQueues.get(userId);
            if (alarmQueue == null) {
                alarmQueue = new LaunchTimeAlarmQueue(
                    userId, getContext(), BackgroundThread.get().getLooper());
                alarmQueue = new LaunchTimeAlarmQueue(userId, getContext(), mHandler.getLooper());
                mLaunchTimeAlarmQueues.put(userId, alarmQueue);
            }

@@ -2040,6 +2050,9 @@ public class UsageStatsService extends SystemService implements
                case MSG_UID_REMOVED:
                    mResponseStatsTracker.onUidRemoved(msg.arg1);
                    break;
                case MSG_USER_STARTED:
                    mAppStandby.postCheckIdleStates(msg.arg1);
                    break;
                case MSG_PACKAGE_REMOVED:
                    onPackageRemoved(msg.arg1, (String) msg.obj);
                    break;