summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2023-06-02 06:15:47 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2023-06-02 06:15:47 +0000
commit649fc122a8e64642fd9bc5cb06563f593768bcd0 (patch)
tree8f5905868fc8579fb87d6aa680c5cf630c5714f7
parent321e06b7beebacf22f22dfd3a8f92de9109e3c2d (diff)
parentf8df9f1dd2a58cbc05421df421f81bfb3da23e59 (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>
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java70
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;
}