diff options
| author | 2024-12-16 07:57:09 -0800 | |
|---|---|---|
| committer | 2024-12-16 07:57:09 -0800 | |
| commit | 8512cdd32e7618b46e47052d23f75e271858ac30 (patch) | |
| tree | 45bae8ad50e796831e3c5e62e37bc959f8934c42 | |
| parent | c7a288da052056a3f9683f1773157ffd061793e2 (diff) | |
| parent | b767ec7c8496a33365d4bc6472c7ef7a572fb1ef (diff) | |
Merge "profcollect: Move periodic trace worker to the system server" into main am: b767ec7c84
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/3396817
Change-Id: I250e1737aaa3c3ed53df4f706c7c6eba863c4ebb
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
3 files changed, 135 insertions, 65 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4be79280a0d3..201e0c8f364e 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -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> diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index 228e32e98cc7..c31594a4bf47 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -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); diff --git a/services/profcollect/src/com/android/server/profcollect/Utils.java b/services/profcollect/src/com/android/server/profcollect/Utils.java index a8016a0b641e..b754ca1875b6 100644 --- a/services/profcollect/src/com/android/server/profcollect/Utils.java +++ b/services/profcollect/src/com/android/server/profcollect/Utils.java @@ -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; + } } |