diff options
| -rw-r--r-- | core/res/AndroidManifest.xml | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/BinaryTransparencyService.java | 86 |
2 files changed, 87 insertions, 3 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 73cdaba24789..d7744e377f12 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -6926,6 +6926,10 @@ android:permission="android.permission.BIND_JOB_SERVICE"> </service> + <service android:name="com.android.server.BinaryTransparencyService$UpdateMeasurementsJobService" + android:permission="android.permission.BIND_JOB_SERVICE"> + </service> + <service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader" android:exported="false"> <intent-filter> diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java index 6986d3bbe585..1f8ef8226c32 100644 --- a/services/core/java/com/android/server/BinaryTransparencyService.java +++ b/services/core/java/com/android/server/BinaryTransparencyService.java @@ -18,14 +18,22 @@ package com.android.server; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.ModuleInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; +import android.os.IBinder; import android.os.RemoteException; import android.os.ResultReceiver; +import android.os.ServiceManager; import android.os.ShellCallback; import android.os.ShellCommand; import android.os.SystemProperties; @@ -42,6 +50,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Executors; import java.util.stream.Collectors; /** @@ -49,6 +58,7 @@ import java.util.stream.Collectors; */ public class BinaryTransparencyService extends SystemService { private static final String TAG = "TransparencyService"; + private static final String EXTRA_SERVICE = "service"; @VisibleForTesting static final String VBMETA_DIGEST_UNINITIALIZED = "vbmeta-digest-uninitialized"; @@ -365,10 +375,80 @@ public class BinaryTransparencyService extends SystemService { // we are only interested in doing things at PHASE_BOOT_COMPLETED if (phase == PHASE_BOOT_COMPLETED) { - // due to potentially long computation that holds up boot time, apex sha computations - // are deferred to first call Slog.i(TAG, "Boot completed. Getting VBMeta Digest."); getVBMetaDigestInformation(); + + // due to potentially long computation that holds up boot time, computations for + // SHA256 digests of APEX and Module packages are scheduled here, + // but only executed when device is idle. + Slog.i(TAG, "Scheduling APEX and Module measurements to be updated."); + UpdateMeasurementsJobService.scheduleBinaryMeasurements(mContext, + BinaryTransparencyService.this); + } + } + + /** + * JobService to update binary measurements and update internal cache. + */ + public static class UpdateMeasurementsJobService extends JobService { + private static final int COMPUTE_APEX_MODULE_SHA256_JOB_ID = + BinaryTransparencyService.UpdateMeasurementsJobService.class.hashCode(); + + @Override + public boolean onStartJob(JobParameters params) { + Slog.d(TAG, "Job to update binary measurements started."); + if (params.getJobId() != COMPUTE_APEX_MODULE_SHA256_JOB_ID) { + return false; + } + + // we'll still update the measurements via threads to be mindful of low-end devices + // where this operation might take longer than expected, and so that we don't block + // system_server's main thread. + Executors.defaultThreadFactory().newThread(() -> { + // since we can't call updateBinaryMeasurements() directly, calling + // getApexInfo() achieves the same effect, and we simply discard the return + // value + + IBinder b = ServiceManager.getService(Context.BINARY_TRANSPARENCY_SERVICE); + IBinaryTransparencyService iBtsService = + IBinaryTransparencyService.Stub.asInterface(b); + try { + iBtsService.getApexInfo(); + } catch (RemoteException e) { + Slog.e(TAG, "Updating binary measurements was interrupted.", e); + return; + } + jobFinished(params, false); + }).start(); + + return true; + } + + @Override + public boolean onStopJob(JobParameters params) { + return false; + } + + @SuppressLint("DefaultLocale") + static void scheduleBinaryMeasurements(Context context, BinaryTransparencyService service) { + Slog.i(TAG, "Scheduling APEX & Module SHA256 digest computation job"); + final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); + if (jobScheduler == null) { + Slog.e(TAG, "Failed to obtain an instance of JobScheduler."); + return; + } + + final JobInfo jobInfo = new JobInfo.Builder(COMPUTE_APEX_MODULE_SHA256_JOB_ID, + new ComponentName(context, UpdateMeasurementsJobService.class)) + .setRequiresDeviceIdle(true) + .build(); + if (jobScheduler.schedule(jobInfo) != JobScheduler.RESULT_SUCCESS) { + Slog.e(TAG, "Failed to schedule job to update binary measurements."); + return; + } + Slog.d(TAG, String.format( + "Job %d to update binary measurements scheduled successfully.", + COMPUTE_APEX_MODULE_SHA256_JOB_ID)); } } @@ -380,7 +460,7 @@ public class BinaryTransparencyService extends SystemService { @NonNull private List<PackageInfo> getInstalledApexs() { - List<PackageInfo> results = new ArrayList<PackageInfo>(); + List<PackageInfo> results = new ArrayList<>(); PackageManager pm = mContext.getPackageManager(); if (pm == null) { Slog.e(TAG, "Error obtaining an instance of PackageManager."); |