Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +6 −2 Original line number Diff line number Diff line Loading @@ -1840,7 +1840,9 @@ public class JobSchedulerService extends com.android.server.SystemService /* isFlexConstraintSatisfied */ false, jobStatus.canApplyTransportAffinities(), jobStatus.getNumAppliedFlexibleConstraints(), jobStatus.getNumDroppedFlexibleConstraints()); jobStatus.getNumDroppedFlexibleConstraints(), jobStatus.getFilteredTraceTag(), jobStatus.getFilteredDebugTags()); // 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 Loading Loading @@ -2288,7 +2290,9 @@ public class JobSchedulerService extends com.android.server.SystemService cancelled.isConstraintSatisfied(JobStatus.CONSTRAINT_FLEXIBLE), cancelled.canApplyTransportAffinities(), cancelled.getNumAppliedFlexibleConstraints(), cancelled.getNumDroppedFlexibleConstraints()); cancelled.getNumDroppedFlexibleConstraints(), cancelled.getFilteredTraceTag(), cancelled.getFilteredDebugTags()); } // If this is a replacement, bring in the new version of the job if (incomingJob != null) { Loading apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +6 −2 Original line number Diff line number Diff line Loading @@ -541,7 +541,9 @@ public final class JobServiceContext implements ServiceConnection { job.isConstraintSatisfied(JobStatus.CONSTRAINT_FLEXIBLE), job.canApplyTransportAffinities(), job.getNumAppliedFlexibleConstraints(), job.getNumDroppedFlexibleConstraints()); job.getNumDroppedFlexibleConstraints(), job.getFilteredTraceTag(), job.getFilteredDebugTags()); sEnqueuedJwiAtJobStart.logSampleWithUid(job.getUid(), job.getWorkCount()); final String sourcePackage = job.getSourcePackageName(); if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { Loading Loading @@ -1630,7 +1632,9 @@ public final class JobServiceContext implements ServiceConnection { completedJob.isConstraintSatisfied(JobStatus.CONSTRAINT_FLEXIBLE), completedJob.canApplyTransportAffinities(), completedJob.getNumAppliedFlexibleConstraints(), completedJob.getNumDroppedFlexibleConstraints()); completedJob.getNumDroppedFlexibleConstraints(), completedJob.getFilteredTraceTag(), completedJob.getFilteredDebugTags()); if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_SYSTEM_SERVER, "JobScheduler", getId()); Loading apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +66 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Pair; import android.util.Patterns; import android.util.Range; import android.util.Slog; import android.util.TimeUtils; Loading Loading @@ -76,6 +77,7 @@ import java.util.Collections; import java.util.Objects; import java.util.Random; import java.util.function.Predicate; import java.util.regex.Pattern; /** * Uniquely identifies a job internally. Loading Loading @@ -203,6 +205,17 @@ public final class JobStatus { // TODO(b/129954980): ensure this doesn't spam statsd, especially at boot private static final boolean STATS_LOG_ENABLED = false; /** * Simple patterns to match some common forms of PII. This is not intended all-encompassing and * any clients should aim to do additional filtering. */ private static final ArrayMap<Pattern, String> BASIC_PII_FILTERS = new ArrayMap<>(); static { BASIC_PII_FILTERS.put(Patterns.EMAIL_ADDRESS, "[EMAIL]"); BASIC_PII_FILTERS.put(Patterns.PHONE, "[PHONE]"); } // No override. public static final int OVERRIDE_NONE = 0; // Override to improve sorting order. Does not affect constraint evaluation. Loading Loading @@ -249,6 +262,18 @@ public final class JobStatus { /** An ID that can be used to uniquely identify the job when logging statsd metrics. */ private final long mLoggingJobId; /** * List of tags from {@link JobInfo#getDebugTags()}, filtered using {@link #BASIC_PII_FILTERS}. * Lazily loaded in {@link #getFilteredDebugTags()}. */ @Nullable private String[] mFilteredDebugTags; /** * Trace tag from {@link JobInfo#getTraceTag()}, filtered using {@link #BASIC_PII_FILTERS}. * Lazily loaded in {@link #getFilteredTraceTag()}. */ @Nullable private String mFilteredTraceTag; /** * Tag to identify the wakelock held for this job. Lazily loaded in * {@link #getWakelockTag()} since it's not typically needed until the job is about to run. Loading Loading @@ -1325,6 +1350,47 @@ public final class JobStatus { return batteryName; } @VisibleForTesting @NonNull static String applyBasicPiiFilters(@NonNull String val) { for (int i = BASIC_PII_FILTERS.size() - 1; i >= 0; --i) { val = BASIC_PII_FILTERS.keyAt(i).matcher(val).replaceAll(BASIC_PII_FILTERS.valueAt(i)); } return val; } /** * List of tags from {@link JobInfo#getDebugTags()}, filtered using a basic set of PII filters. */ @NonNull public String[] getFilteredDebugTags() { if (mFilteredDebugTags != null) { return mFilteredDebugTags; } final ArraySet<String> debugTags = job.getDebugTagsArraySet(); mFilteredDebugTags = new String[debugTags.size()]; for (int i = 0; i < mFilteredDebugTags.length; ++i) { mFilteredDebugTags[i] = applyBasicPiiFilters(debugTags.valueAt(i)); } return mFilteredDebugTags; } /** * Trace tag from {@link JobInfo#getTraceTag()}, filtered using a basic set of PII filters. */ @Nullable public String getFilteredTraceTag() { if (mFilteredTraceTag != null) { return mFilteredTraceTag; } final String rawTag = job.getTraceTag(); if (rawTag == null) { return null; } mFilteredTraceTag = applyBasicPiiFilters(rawTag); return mFilteredTraceTag; } /** Return the String to be used as the tag for the wakelock held for this job. */ @NonNull public String getWakelockTag() { Loading services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java +67 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import static com.android.server.job.controllers.JobStatus.CONSTRAINT_WITHIN_QUO import static com.android.server.job.controllers.JobStatus.NO_EARLIEST_RUNTIME; import static com.android.server.job.controllers.JobStatus.NO_LATEST_RUNTIME; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; Loading Loading @@ -78,6 +79,7 @@ import org.mockito.quality.Strictness; import java.time.Clock; import java.time.ZoneOffset; import java.util.Arrays; @RunWith(AndroidJUnit4.class) public class JobStatusTest { Loading Loading @@ -137,6 +139,35 @@ public class JobStatusTest { } } @Test public void testApplyBasicPiiFilters_email() { assertEquals("[EMAIL]", JobStatus.applyBasicPiiFilters("test@email.com")); assertEquals("[EMAIL]", JobStatus.applyBasicPiiFilters("test+plus@email.com")); assertEquals("[EMAIL]", JobStatus.applyBasicPiiFilters("t.e_st+plus-minus@email.com")); assertEquals("prefix:[EMAIL]", JobStatus.applyBasicPiiFilters("prefix:test@email.com")); assertEquals("not-an-email", JobStatus.applyBasicPiiFilters("not-an-email")); } @Test public void testApplyBasicPiiFilters_mixture() { assertEquals("[PHONE]:[EMAIL]", JobStatus.applyBasicPiiFilters("123-456-7890:test+plus@email.com")); assertEquals("prefix:[PHONE]:[EMAIL]", JobStatus.applyBasicPiiFilters("prefix:123-456-7890:test+plus@email.com")); } @Test public void testApplyBasicPiiFilters_phone() { assertEquals("[PHONE]", JobStatus.applyBasicPiiFilters("123-456-7890")); assertEquals("[PHONE]", JobStatus.applyBasicPiiFilters("+1-234-567-8900")); assertEquals("prefix:[PHONE]", JobStatus.applyBasicPiiFilters("prefix:123-456-7890")); assertEquals("not-a-phone-number", JobStatus.applyBasicPiiFilters("not-a-phone-number")); } @Test public void testCanRunInBatterySaver_regular() { final JobInfo jobInfo = Loading Loading @@ -244,6 +275,42 @@ public class JobStatusTest { assertEquals(1, js.getNumRequiredFlexibleConstraints()); } @Test public void testGetFilteredDebugTags() { final JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) .addDebugTag("test@email.com") .addDebugTag("123-456-7890") .addDebugTag("random") .build(); JobStatus job = createJobStatus(jobInfo); String[] expected = new String[]{"[EMAIL]", "[PHONE]", "random"}; String[] result = job.getFilteredDebugTags(); Arrays.sort(expected); Arrays.sort(result); assertArrayEquals(expected, result); } @Test public void testGetFilteredTraceTag() { JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) .setTraceTag("test@email.com") .build(); JobStatus job = createJobStatus(jobInfo); assertEquals("[EMAIL]", job.getFilteredTraceTag()); jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) .setTraceTag("123-456-7890") .build(); job = createJobStatus(jobInfo); assertEquals("[PHONE]", job.getFilteredTraceTag()); jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) .setTraceTag("random") .build(); job = createJobStatus(jobInfo); assertEquals("random", job.getFilteredTraceTag()); } @Test public void testIsUserVisibleJob() { JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) Loading Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +6 −2 Original line number Diff line number Diff line Loading @@ -1840,7 +1840,9 @@ public class JobSchedulerService extends com.android.server.SystemService /* isFlexConstraintSatisfied */ false, jobStatus.canApplyTransportAffinities(), jobStatus.getNumAppliedFlexibleConstraints(), jobStatus.getNumDroppedFlexibleConstraints()); jobStatus.getNumDroppedFlexibleConstraints(), jobStatus.getFilteredTraceTag(), jobStatus.getFilteredDebugTags()); // 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 Loading Loading @@ -2288,7 +2290,9 @@ public class JobSchedulerService extends com.android.server.SystemService cancelled.isConstraintSatisfied(JobStatus.CONSTRAINT_FLEXIBLE), cancelled.canApplyTransportAffinities(), cancelled.getNumAppliedFlexibleConstraints(), cancelled.getNumDroppedFlexibleConstraints()); cancelled.getNumDroppedFlexibleConstraints(), cancelled.getFilteredTraceTag(), cancelled.getFilteredDebugTags()); } // If this is a replacement, bring in the new version of the job if (incomingJob != null) { Loading
apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +6 −2 Original line number Diff line number Diff line Loading @@ -541,7 +541,9 @@ public final class JobServiceContext implements ServiceConnection { job.isConstraintSatisfied(JobStatus.CONSTRAINT_FLEXIBLE), job.canApplyTransportAffinities(), job.getNumAppliedFlexibleConstraints(), job.getNumDroppedFlexibleConstraints()); job.getNumDroppedFlexibleConstraints(), job.getFilteredTraceTag(), job.getFilteredDebugTags()); sEnqueuedJwiAtJobStart.logSampleWithUid(job.getUid(), job.getWorkCount()); final String sourcePackage = job.getSourcePackageName(); if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { Loading Loading @@ -1630,7 +1632,9 @@ public final class JobServiceContext implements ServiceConnection { completedJob.isConstraintSatisfied(JobStatus.CONSTRAINT_FLEXIBLE), completedJob.canApplyTransportAffinities(), completedJob.getNumAppliedFlexibleConstraints(), completedJob.getNumDroppedFlexibleConstraints()); completedJob.getNumDroppedFlexibleConstraints(), completedJob.getFilteredTraceTag(), completedJob.getFilteredDebugTags()); if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_SYSTEM_SERVER, "JobScheduler", getId()); Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +66 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Pair; import android.util.Patterns; import android.util.Range; import android.util.Slog; import android.util.TimeUtils; Loading Loading @@ -76,6 +77,7 @@ import java.util.Collections; import java.util.Objects; import java.util.Random; import java.util.function.Predicate; import java.util.regex.Pattern; /** * Uniquely identifies a job internally. Loading Loading @@ -203,6 +205,17 @@ public final class JobStatus { // TODO(b/129954980): ensure this doesn't spam statsd, especially at boot private static final boolean STATS_LOG_ENABLED = false; /** * Simple patterns to match some common forms of PII. This is not intended all-encompassing and * any clients should aim to do additional filtering. */ private static final ArrayMap<Pattern, String> BASIC_PII_FILTERS = new ArrayMap<>(); static { BASIC_PII_FILTERS.put(Patterns.EMAIL_ADDRESS, "[EMAIL]"); BASIC_PII_FILTERS.put(Patterns.PHONE, "[PHONE]"); } // No override. public static final int OVERRIDE_NONE = 0; // Override to improve sorting order. Does not affect constraint evaluation. Loading Loading @@ -249,6 +262,18 @@ public final class JobStatus { /** An ID that can be used to uniquely identify the job when logging statsd metrics. */ private final long mLoggingJobId; /** * List of tags from {@link JobInfo#getDebugTags()}, filtered using {@link #BASIC_PII_FILTERS}. * Lazily loaded in {@link #getFilteredDebugTags()}. */ @Nullable private String[] mFilteredDebugTags; /** * Trace tag from {@link JobInfo#getTraceTag()}, filtered using {@link #BASIC_PII_FILTERS}. * Lazily loaded in {@link #getFilteredTraceTag()}. */ @Nullable private String mFilteredTraceTag; /** * Tag to identify the wakelock held for this job. Lazily loaded in * {@link #getWakelockTag()} since it's not typically needed until the job is about to run. Loading Loading @@ -1325,6 +1350,47 @@ public final class JobStatus { return batteryName; } @VisibleForTesting @NonNull static String applyBasicPiiFilters(@NonNull String val) { for (int i = BASIC_PII_FILTERS.size() - 1; i >= 0; --i) { val = BASIC_PII_FILTERS.keyAt(i).matcher(val).replaceAll(BASIC_PII_FILTERS.valueAt(i)); } return val; } /** * List of tags from {@link JobInfo#getDebugTags()}, filtered using a basic set of PII filters. */ @NonNull public String[] getFilteredDebugTags() { if (mFilteredDebugTags != null) { return mFilteredDebugTags; } final ArraySet<String> debugTags = job.getDebugTagsArraySet(); mFilteredDebugTags = new String[debugTags.size()]; for (int i = 0; i < mFilteredDebugTags.length; ++i) { mFilteredDebugTags[i] = applyBasicPiiFilters(debugTags.valueAt(i)); } return mFilteredDebugTags; } /** * Trace tag from {@link JobInfo#getTraceTag()}, filtered using a basic set of PII filters. */ @Nullable public String getFilteredTraceTag() { if (mFilteredTraceTag != null) { return mFilteredTraceTag; } final String rawTag = job.getTraceTag(); if (rawTag == null) { return null; } mFilteredTraceTag = applyBasicPiiFilters(rawTag); return mFilteredTraceTag; } /** Return the String to be used as the tag for the wakelock held for this job. */ @NonNull public String getWakelockTag() { Loading
services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java +67 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import static com.android.server.job.controllers.JobStatus.CONSTRAINT_WITHIN_QUO import static com.android.server.job.controllers.JobStatus.NO_EARLIEST_RUNTIME; import static com.android.server.job.controllers.JobStatus.NO_LATEST_RUNTIME; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; Loading Loading @@ -78,6 +79,7 @@ import org.mockito.quality.Strictness; import java.time.Clock; import java.time.ZoneOffset; import java.util.Arrays; @RunWith(AndroidJUnit4.class) public class JobStatusTest { Loading Loading @@ -137,6 +139,35 @@ public class JobStatusTest { } } @Test public void testApplyBasicPiiFilters_email() { assertEquals("[EMAIL]", JobStatus.applyBasicPiiFilters("test@email.com")); assertEquals("[EMAIL]", JobStatus.applyBasicPiiFilters("test+plus@email.com")); assertEquals("[EMAIL]", JobStatus.applyBasicPiiFilters("t.e_st+plus-minus@email.com")); assertEquals("prefix:[EMAIL]", JobStatus.applyBasicPiiFilters("prefix:test@email.com")); assertEquals("not-an-email", JobStatus.applyBasicPiiFilters("not-an-email")); } @Test public void testApplyBasicPiiFilters_mixture() { assertEquals("[PHONE]:[EMAIL]", JobStatus.applyBasicPiiFilters("123-456-7890:test+plus@email.com")); assertEquals("prefix:[PHONE]:[EMAIL]", JobStatus.applyBasicPiiFilters("prefix:123-456-7890:test+plus@email.com")); } @Test public void testApplyBasicPiiFilters_phone() { assertEquals("[PHONE]", JobStatus.applyBasicPiiFilters("123-456-7890")); assertEquals("[PHONE]", JobStatus.applyBasicPiiFilters("+1-234-567-8900")); assertEquals("prefix:[PHONE]", JobStatus.applyBasicPiiFilters("prefix:123-456-7890")); assertEquals("not-a-phone-number", JobStatus.applyBasicPiiFilters("not-a-phone-number")); } @Test public void testCanRunInBatterySaver_regular() { final JobInfo jobInfo = Loading Loading @@ -244,6 +275,42 @@ public class JobStatusTest { assertEquals(1, js.getNumRequiredFlexibleConstraints()); } @Test public void testGetFilteredDebugTags() { final JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) .addDebugTag("test@email.com") .addDebugTag("123-456-7890") .addDebugTag("random") .build(); JobStatus job = createJobStatus(jobInfo); String[] expected = new String[]{"[EMAIL]", "[PHONE]", "random"}; String[] result = job.getFilteredDebugTags(); Arrays.sort(expected); Arrays.sort(result); assertArrayEquals(expected, result); } @Test public void testGetFilteredTraceTag() { JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) .setTraceTag("test@email.com") .build(); JobStatus job = createJobStatus(jobInfo); assertEquals("[EMAIL]", job.getFilteredTraceTag()); jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) .setTraceTag("123-456-7890") .build(); job = createJobStatus(jobInfo); assertEquals("[PHONE]", job.getFilteredTraceTag()); jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) .setTraceTag("random") .build(); job = createJobStatus(jobInfo); assertEquals("random", job.getFilteredTraceTag()); } @Test public void testIsUserVisibleJob() { JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar")) Loading