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

Commit 8512cdd3 authored by Yi Kong's avatar Yi Kong Committed by Automerger Merge Worker
Browse files

Merge "profcollect: Move periodic trace worker to the system server" into main am: b767ec7c

parents c7a288da b767ec7c
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -8980,7 +8980,11 @@
                 android:permission="android.permission.BIND_JOB_SERVICE" >
        </service>

        <service android:name="com.android.server.profcollect.ProfcollectForwardingService$ProfcollectBGJobService"
        <service android:name="com.android.server.profcollect.ProfcollectForwardingService$PeriodicTraceJobService"
                 android:permission="android.permission.BIND_JOB_SERVICE" >
        </service>

        <service android:name="com.android.server.profcollect.ProfcollectForwardingService$ReportProcessJobService"
                 android:permission="android.permission.BIND_JOB_SERVICE" >
        </service>

+95 −44
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.server.profcollect;

import static android.content.Intent.ACTION_SCREEN_OFF;
import static android.content.Intent.ACTION_SCREEN_ON;

import android.Manifest;
import android.annotation.RequiresPermission;
import android.app.job.JobInfo;
@@ -32,6 +35,7 @@ import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.IBinder.DeathRecipient;
import android.os.Looper;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -70,10 +74,11 @@ public final class ProfcollectForwardingService extends SystemService {
    private int mUsageSetting;
    private boolean mUploadEnabled;

    private static boolean sVerityEnforced;
    private boolean mAdbActive;
    static boolean sVerityEnforced;
    static boolean sIsInteractive;
    static boolean sAdbActive;

    private IProfCollectd mIProfcollect;
    private static IProfCollectd sIProfcollect;
    private static ProfcollectForwardingService sSelfService;
    private final Handler mHandler = new ProfcollectdHandler(IoThread.getHandler().getLooper());

@@ -86,17 +91,24 @@ public final class ProfcollectForwardingService extends SystemService {
    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (INTENT_UPLOAD_PROFILES.equals(intent.getAction())) {
            if (ACTION_SCREEN_ON.equals(intent.getAction())) {
                Log.d(LOG_TAG, "Received broadcast that the device became interactive, was "
                        + sIsInteractive);
                sIsInteractive = true;
            } else if (ACTION_SCREEN_OFF.equals(intent.getAction())) {
                Log.d(LOG_TAG, "Received broadcast that the device became noninteractive, was "
                        + sIsInteractive);
                sIsInteractive = false;
            } else if (INTENT_UPLOAD_PROFILES.equals(intent.getAction())) {
                Log.d(LOG_TAG, "Received broadcast to pack and upload reports");
                createAndUploadReport(sSelfService);
            }
            if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) {
            } else if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) {
                boolean isADB = intent.getBooleanExtra(UsbManager.USB_FUNCTION_ADB, false);
                if (isADB) {
                    boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
                    Log.d(LOG_TAG, "Received broadcast that ADB became " + connected
                            + ", was " + mAdbActive);
                    mAdbActive = connected;
                            + ", was " + sAdbActive);
                    sAdbActive = connected;
                }
            }
        }
@@ -129,6 +141,8 @@ public final class ProfcollectForwardingService extends SystemService {
            context.getResources().getBoolean(R.bool.config_profcollectReportUploaderEnabled);

        final IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_SCREEN_ON);
        filter.addAction(ACTION_SCREEN_OFF);
        filter.addAction(INTENT_UPLOAD_PROFILES);
        filter.addAction(UsbManager.ACTION_USB_STATE);
        context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
@@ -153,14 +167,24 @@ public final class ProfcollectForwardingService extends SystemService {
        if (phase == PHASE_SYSTEM_SERVICES_READY) {
            UsbManager usbManager = getContext().getSystemService(UsbManager.class);
            if (usbManager == null) {
                mAdbActive = false;
                return;
                sAdbActive = false;
                Log.d(LOG_TAG, "USBManager is not ready");
            } else {
                sAdbActive = ((usbManager.getCurrentFunctions() & UsbManager.FUNCTION_ADB) == 1);
                Log.d(LOG_TAG, "ADB is " + sAdbActive + " on system startup");
            }

            PowerManager powerManager = getContext().getSystemService(PowerManager.class);
            if (powerManager == null) {
                sIsInteractive = true;
                Log.d(LOG_TAG, "PowerManager is not ready");
            } else {
                sIsInteractive = powerManager.isInteractive();
                Log.d(LOG_TAG, "Device is interactive " + sIsInteractive + " on system startup");
            }
            mAdbActive = ((usbManager.getCurrentFunctions() & UsbManager.FUNCTION_ADB) == 1);
            Log.d(LOG_TAG, "ADB is " + mAdbActive + " on system startup");
        }
        if (phase == PHASE_BOOT_COMPLETED) {
            if (mIProfcollect == null) {
            if (sIProfcollect == null) {
                return;
            }
            BackgroundThread.get().getThreadHandler().post(() -> {
@@ -172,22 +196,22 @@ public final class ProfcollectForwardingService extends SystemService {
    }

    private void registerProviderStatusCallback() {
        if (mIProfcollect == null) {
        if (sIProfcollect == null) {
            return;
        }
        try {
            mIProfcollect.registerProviderStatusCallback(mProviderStatusCallback);
            sIProfcollect.registerProviderStatusCallback(mProviderStatusCallback);
        } catch (RemoteException e) {
            Log.e(LOG_TAG, "Failed to register provider status callback: " + e.getMessage());
        }
    }

    private boolean serviceHasSupportedTraceProvider() {
        if (mIProfcollect == null) {
        if (sIProfcollect == null) {
            return false;
        }
        try {
            return !mIProfcollect.get_supported_provider().isEmpty();
            return !sIProfcollect.get_supported_provider().isEmpty();
        } catch (RemoteException e) {
            Log.e(LOG_TAG, "Failed to get supported provider: " + e.getMessage());
            return false;
@@ -209,7 +233,7 @@ public final class ProfcollectForwardingService extends SystemService {
                    IProfCollectd.Stub.asInterface(
                            ServiceManager.getServiceOrThrow("profcollectd"));
            profcollectd.asBinder().linkToDeath(new ProfcollectdDeathRecipient(), /*flags*/0);
            mIProfcollect = profcollectd;
            sIProfcollect = profcollectd;
            return true;
        } catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
            Log.w(LOG_TAG, "Failed to connect profcollectd binder service.");
@@ -233,7 +257,8 @@ public final class ProfcollectForwardingService extends SystemService {
                    break;
                case MESSAGE_REGISTER_SCHEDULERS:
                    registerObservers();
                    ProfcollectBGJobService.schedule(getContext());
                    PeriodicTraceJobService.schedule(getContext());
                    ReportProcessJobService.schedule(getContext());
                    break;
                default:
                    throw new AssertionError("Unknown message: " + message);
@@ -246,27 +271,66 @@ public final class ProfcollectForwardingService extends SystemService {
        public void binderDied() {
            Log.w(LOG_TAG, "profcollectd has died");

            mIProfcollect = null;
            sIProfcollect = null;
            tryConnectNativeService();
        }
    }

    /**
     * Background trace process service.
     * Background report process and upload service.
     */
    public static class ProfcollectBGJobService extends JobService {
        // Unique ID in system service
        private static final int JOB_IDLE_PROCESS = 260817;
    public static class PeriodicTraceJobService extends JobService {
        // Unique ID in system server
        private static final int PERIODIC_TRACE_JOB_ID = 241207;
        private static final ComponentName JOB_SERVICE_NAME = new ComponentName(
                "android",
                ProfcollectBGJobService.class.getName());
                PeriodicTraceJobService.class.getName());

        /**
         * Attach the service to the system job scheduler.
         */
        public static void schedule(Context context) {
            final int interval = DeviceConfig.getInt(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
                    "collection_interval", 600);
            JobScheduler js = context.getSystemService(JobScheduler.class);
            js.schedule(new JobInfo.Builder(JOB_IDLE_PROCESS, JOB_SERVICE_NAME)
            js.schedule(new JobInfo.Builder(PERIODIC_TRACE_JOB_ID, JOB_SERVICE_NAME)
                    .setPeriodic(TimeUnit.SECONDS.toMillis(interval))
                    // PRIORITY_DEFAULT is the highest priority we can request for a periodic job.
                    .setPriority(JobInfo.PRIORITY_DEFAULT)
                    .build());
        }

        @Override
        public boolean onStartJob(JobParameters params) {
            if (sIProfcollect != null) {
                Utils.traceSystem(sIProfcollect, "periodic");
            }
            jobFinished(params, false);
            return true;
        }

        @Override
        public boolean onStopJob(JobParameters params) {
            return false;
        }
    }

    /**
     * Background report process and upload service.
     */
    public static class ReportProcessJobService extends JobService {
        // Unique ID in system server
        private static final int REPORT_PROCESS_JOB_ID = 260817;
        private static final ComponentName JOB_SERVICE_NAME = new ComponentName(
                "android",
                ReportProcessJobService.class.getName());

        /**
         * Attach the service to the system job scheduler.
         */
        public static void schedule(Context context) {
            JobScheduler js = context.getSystemService(JobScheduler.class);
            js.schedule(new JobInfo.Builder(REPORT_PROCESS_JOB_ID, JOB_SERVICE_NAME)
                    .setRequiresDeviceIdle(true)
                    .setRequiresCharging(true)
                    .setPeriodic(BG_PROCESS_INTERVAL)
@@ -283,7 +347,6 @@ public final class ProfcollectForwardingService extends SystemService {

        @Override
        public boolean onStopJob(JobParameters params) {
            // TODO: Handle this?
            return false;
        }
    }
@@ -311,14 +374,8 @@ public final class ProfcollectForwardingService extends SystemService {
    private class AppLaunchObserver extends ActivityMetricsLaunchObserver {
        @Override
        public void onIntentStarted(Intent intent, long timestampNanos) {
            if (mIProfcollect == null) {
                return;
            }
            if (mAdbActive) {
                return;
            }
            if (Utils.withFrequency("applaunch_trace_freq", 5)) {
                Utils.traceSystem(mIProfcollect, "applaunch");
                Utils.traceSystem(sIProfcollect, "applaunch");
            }
        }
    }
@@ -336,15 +393,9 @@ public final class ProfcollectForwardingService extends SystemService {
    }

    private void traceOnDex2oatStart() {
        if (mIProfcollect == null) {
            return;
        }
        if (mAdbActive) {
            return;
        }
        if (Utils.withFrequency("dex2oat_trace_freq", 25)) {
            // Dex2oat could take a while before it starts. Add a short delay before start tracing.
            Utils.traceSystem(mIProfcollect, "dex2oat", /* delayMs */ 1000);
            Utils.traceSystem(sIProfcollect, "dex2oat", /* delayMs */ 1000);
        }
    }

@@ -367,12 +418,12 @@ public final class ProfcollectForwardingService extends SystemService {

    private static void createAndUploadReport(ProfcollectForwardingService pfs) {
        BackgroundThread.get().getThreadHandler().post(() -> {
            if (pfs.mIProfcollect == null) {
            if (pfs.sIProfcollect == null) {
                return;
            }
            String reportName;
            try {
                reportName = pfs.mIProfcollect.report(pfs.mUsageSetting) + ".zip";
                reportName = pfs.sIProfcollect.report(pfs.mUsageSetting) + ".zip";
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Failed to create report: " + e.getMessage());
                return;
@@ -411,7 +462,7 @@ public final class ProfcollectForwardingService extends SystemService {
                    return;
                }
                if (Utils.withFrequency("camera_trace_freq", 10)) {
                    Utils.traceProcess(mIProfcollect,
                    Utils.traceProcess(sIProfcollect,
                            "camera",
                            "android.hardware.camera.provider",
                            /* durationMs */ 5000);
+35 −20
Original line number Diff line number Diff line
@@ -28,28 +28,29 @@ import com.android.internal.os.BackgroundThread;
import java.time.Instant;
import java.util.concurrent.ThreadLocalRandom;

public final class Utils {
final class Utils {

    private static Instant lastTraceTime = Instant.EPOCH;
    private static final int TRACE_COOLDOWN_SECONDS = 30;

    public static boolean withFrequency(String configName, int defaultFrequency) {
    static boolean withFrequency(String configName, int defaultFrequency) {
        int threshold = DeviceConfig.getInt(
                DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, configName, defaultFrequency);
        int randomNum = ThreadLocalRandom.current().nextInt(100);
        return randomNum < threshold;
    }

    public static boolean traceSystem(IProfCollectd mIProfcollect, String eventName) {
        if (mIProfcollect == null) {
            return false;
        }
        if (isInCooldownOrReset()) {
    /**
     * Request a system-wide trace.
     * Will be ignored if the device does not meet trace criteria or is being rate limited.
     */
    static boolean traceSystem(IProfCollectd iprofcollectd, String eventName) {
        if (!checkPrerequisites(iprofcollectd)) {
            return false;
        }
        BackgroundThread.get().getThreadHandler().post(() -> {
            try {
                mIProfcollect.trace_system(eventName);
                iprofcollectd.trace_system(eventName);
            } catch (RemoteException | ServiceSpecificException e) {
                Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
            }
@@ -57,16 +58,17 @@ public final class Utils {
        return true;
    }

    public static boolean traceSystem(IProfCollectd mIProfcollect, String eventName, int delayMs) {
        if (mIProfcollect == null) {
            return false;
        }
        if (isInCooldownOrReset()) {
    /**
     * Request a system-wide trace after a delay.
     * Will be ignored if the device does not meet trace criteria or is being rate limited.
     */
    static boolean traceSystem(IProfCollectd iprofcollectd, String eventName, int delayMs) {
        if (!checkPrerequisites(iprofcollectd)) {
            return false;
        }
        BackgroundThread.get().getThreadHandler().postDelayed(() -> {
            try {
                mIProfcollect.trace_system(eventName);
                iprofcollectd.trace_system(eventName);
            } catch (RemoteException | ServiceSpecificException e) {
                Log.e(LOG_TAG, "Failed to initiate trace: " + e.getMessage());
            }
@@ -74,17 +76,18 @@ public final class Utils {
        return true;
    }

    public static boolean traceProcess(IProfCollectd mIProfcollect,
    /**
     * Request a single-process trace.
     * Will be ignored if the device does not meet trace criteria or is being rate limited.
     */
    static boolean traceProcess(IProfCollectd iprofcollectd,
            String eventName, String processName, int durationMs) {
        if (mIProfcollect == null) {
            return false;
        }
        if (isInCooldownOrReset()) {
        if (!checkPrerequisites(iprofcollectd)) {
            return false;
        }
        BackgroundThread.get().getThreadHandler().post(() -> {
            try {
                mIProfcollect.trace_process(eventName,
                iprofcollectd.trace_process(eventName,
                        processName,
                        durationMs);
            } catch (RemoteException | ServiceSpecificException e) {
@@ -105,4 +108,16 @@ public final class Utils {
        }
        return true;
    }

    private static boolean checkPrerequisites(IProfCollectd iprofcollectd) {
        if (iprofcollectd == null) {
            return false;
        }
        if (isInCooldownOrReset()) {
            return false;
        }
        return ProfcollectForwardingService.sVerityEnforced
            && !ProfcollectForwardingService.sAdbActive
            && ProfcollectForwardingService.sIsInteractive;
    }
}