diff options
author | 2023-06-02 06:15:47 +0000 | |
---|---|---|
committer | 2023-06-02 06:15:47 +0000 | |
commit | 649fc122a8e64642fd9bc5cb06563f593768bcd0 (patch) | |
tree | 8f5905868fc8579fb87d6aa680c5cf630c5714f7 | |
parent | 321e06b7beebacf22f22dfd3a8f92de9109e3c2d (diff) | |
parent | f8df9f1dd2a58cbc05421df421f81bfb3da23e59 (diff) |
Merge "Log namespace hash." into udc-dev am: f8df9f1dd2
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23168112
Change-Id: I2405c66fc264ac67e12a0fcc34d35e7d42305414
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
3 files changed, 78 insertions, 4 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index 4f5eb37d871d..cbc9263a2c3d 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -1631,7 +1631,8 @@ public class JobSchedulerService extends com.android.server.SystemService jobStatus.getEstimatedNetworkDownloadBytes(), jobStatus.getEstimatedNetworkUploadBytes(), jobStatus.getWorkCount(), - ActivityManager.processStateAmToProto(mUidProcStates.get(jobStatus.getUid()))); + ActivityManager.processStateAmToProto(mUidProcStates.get(jobStatus.getUid())), + jobStatus.getNamespaceHash()); // If the job is immediately ready to run, then we can just immediately // put it in the pending list and try to schedule it. This is especially @@ -2059,7 +2060,8 @@ public class JobSchedulerService extends com.android.server.SystemService cancelled.getEstimatedNetworkDownloadBytes(), cancelled.getEstimatedNetworkUploadBytes(), cancelled.getWorkCount(), - ActivityManager.processStateAmToProto(mUidProcStates.get(cancelled.getUid()))); + ActivityManager.processStateAmToProto(mUidProcStates.get(cancelled.getUid())), + cancelled.getNamespaceHash()); } // If this is a replacement, bring in the new version of the job if (incomingJob != null) { diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java index 90f1523104ee..0b08b6faf971 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java @@ -499,7 +499,8 @@ public final class JobServiceContext implements ServiceConnection { job.getEstimatedNetworkDownloadBytes(), job.getEstimatedNetworkUploadBytes(), job.getWorkCount(), - ActivityManager.processStateAmToProto(mService.getUidProcState(job.getUid()))); + ActivityManager.processStateAmToProto(mService.getUidProcState(job.getUid())), + job.getNamespaceHash()); sEnqueuedJwiAtJobStart.logSampleWithUid(job.getUid(), job.getWorkCount()); final String sourcePackage = job.getSourcePackageName(); if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { @@ -1557,7 +1558,8 @@ public final class JobServiceContext implements ServiceConnection { completedJob.getEstimatedNetworkUploadBytes(), completedJob.getWorkCount(), ActivityManager - .processStateAmToProto(mService.getUidProcState(completedJob.getUid()))); + .processStateAmToProto(mService.getUidProcState(completedJob.getUid())), + completedJob.getNamespaceHash()); if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_SYSTEM_SERVER, "JobScheduler", getId()); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java index a8b4c695889c..edd531d13965 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java @@ -43,6 +43,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.provider.MediaStore; import android.text.format.DateFormat; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Pair; @@ -51,6 +52,7 @@ import android.util.Slog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; @@ -65,10 +67,12 @@ import com.android.server.job.JobStatusShortInfoProto; import dalvik.annotation.optimization.NeverCompile; import java.io.PrintWriter; +import java.security.MessageDigest; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Objects; +import java.util.Random; import java.util.function.Predicate; /** @@ -88,6 +92,13 @@ public final class JobStatus { private static final String TAG = "JobScheduler.JobStatus"; static final boolean DEBUG = JobSchedulerService.DEBUG; + private static MessageDigest sMessageDigest; + /** Cache of namespace to hash to reduce how often we need to generate the namespace hash. */ + @GuardedBy("sNamespaceHashCache") + private static final ArrayMap<String, String> sNamespaceHashCache = new ArrayMap<>(); + /** Maximum size of {@link #sNamespaceHashCache}. */ + private static final int MAX_NAMESPACE_CACHE_SIZE = 128; + private static final int NUM_CONSTRAINT_CHANGE_HISTORY = 10; public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE; @@ -231,6 +242,8 @@ public final class JobStatus { final String sourceTag; @Nullable private final String mNamespace; + @Nullable + private final String mNamespaceHash; /** An ID that can be used to uniquely identify the job when logging statsd metrics. */ private final long mLoggingJobId; @@ -570,6 +583,7 @@ public final class JobStatus { this.callingUid = callingUid; this.standbyBucket = standbyBucket; mNamespace = namespace; + mNamespaceHash = generateNamespaceHash(namespace); mLoggingJobId = generateLoggingId(namespace, job.getId()); int tempSourceUid = -1; @@ -814,6 +828,56 @@ public final class JobStatus { return ((long) namespace.hashCode()) << 31 | jobId; } + @Nullable + private static String generateNamespaceHash(@Nullable String namespace) { + if (namespace == null) { + return null; + } + if (namespace.trim().isEmpty()) { + // Input is composed of all spaces (or nothing at all). + return namespace; + } + synchronized (sNamespaceHashCache) { + final int idx = sNamespaceHashCache.indexOfKey(namespace); + if (idx >= 0) { + return sNamespaceHashCache.valueAt(idx); + } + } + String hash = null; + try { + // .hashCode() can result in conflicts that would make distinguishing between + // namespaces hard and reduce the accuracy of certain metrics. Use SHA-256 + // to generate the hash since the probability of collision is extremely low. + if (sMessageDigest == null) { + sMessageDigest = MessageDigest.getInstance("SHA-256"); + } + final byte[] digest = sMessageDigest.digest(namespace.getBytes()); + // Convert to hexadecimal representation + StringBuilder hexBuilder = new StringBuilder(digest.length); + for (byte byteChar : digest) { + hexBuilder.append(String.format("%02X", byteChar)); + } + hash = hexBuilder.toString(); + } catch (Exception e) { + Slog.wtf(TAG, "Couldn't hash input", e); + } + if (hash == null) { + // If we get to this point, something went wrong with the MessageDigest above. + // Don't return the raw input value (which would defeat the purpose of hashing). + return "failed_namespace_hash"; + } + hash = hash.intern(); + synchronized (sNamespaceHashCache) { + if (sNamespaceHashCache.size() >= MAX_NAMESPACE_CACHE_SIZE) { + // Drop a random mapping instead of dropping at a predefined index to avoid + // potentially always dropping the same mapping. + sNamespaceHashCache.removeAt((new Random()).nextInt(MAX_NAMESPACE_CACHE_SIZE)); + } + sNamespaceHashCache.put(namespace, hash); + } + return hash; + } + public void enqueueWorkLocked(JobWorkItem work) { if (pendingWork == null) { pendingWork = new ArrayList<>(); @@ -1117,10 +1181,16 @@ public final class JobStatus { return true; } + @Nullable public String getNamespace() { return mNamespace; } + @Nullable + public String getNamespaceHash() { + return mNamespaceHash; + } + public String getSourceTag() { return sourceTag; } |