Add logging to statsd for job constraint changes.
Bug: 117846754
Bug: 111423978
Bug: 120941744
Test: `make statsd_testdrive &&
./out/host/linux-x86/bin/statsd_testdrive 150` and check output
Change-Id: Iadfdb07171b8d4f99b8f57008cc7c1fc2865bb8e
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 8e56bef..e84eced 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -33,6 +33,7 @@
import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/core/proto/android/server/connectivity/data_stall_event.proto";
import "frameworks/base/core/proto/android/server/enums.proto";
+import "frameworks/base/core/proto/android/server/job/enums.proto";
import "frameworks/base/core/proto/android/server/location/enums.proto";
import "frameworks/base/core/proto/android/service/procstats_enum.proto";
import "frameworks/base/core/proto/android/service/usb.proto";
@@ -213,6 +214,7 @@
WatchdogRollbackOccurred watchdog_rollback_occurred = 147;
BiometricHalDeathReported biometric_hal_death_reported = 148;
BubbleUIChanged bubble_ui_changed = 149;
+ ScheduledJobConstraintChanged scheduled_job_constraint_changed = 150;
}
// Pulled events will start at field 10000.
@@ -4699,3 +4701,24 @@
optional float normalized_x_position = 7;
optional float normalized_y_position = 8;
}
+
+/**
+ * Logs that a constraint for a scheduled job has changed.
+ *
+ * Logged from:
+ * frameworks/base/services/core/java/com/android/server/job/controllers/JobStatus.java
+ */
+message ScheduledJobConstraintChanged {
+ repeated AttributionNode attribution_node = 1;
+
+ // Name of the job.
+ optional string job_name = 2;
+
+ optional com.android.server.job.ConstraintEnum constraint = 3;
+
+ enum State {
+ UNSATISFIED = 0;
+ SATISFIED = 1;
+ }
+ optional State state = 4;
+}
diff --git a/core/proto/android/app/job/enums.proto b/core/proto/android/app/job/enums.proto
index bba8328..f702b3e 100644
--- a/core/proto/android/app/job/enums.proto
+++ b/core/proto/android/app/job/enums.proto
@@ -18,6 +18,9 @@
package android.app.job;
+// This file is for JobScheduler enums inside the app directory. If you're
+// adding enums for system-server-side code, use the file in
+// frameworks/base/core/proto/android/server/job.
option java_outer_classname = "JobProtoEnums";
option java_multiple_files = true;
diff --git a/core/proto/android/server/job/enums.proto b/core/proto/android/server/job/enums.proto
new file mode 100644
index 0000000..50fc031
--- /dev/null
+++ b/core/proto/android/server/job/enums.proto
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package com.android.server.job;
+
+// This file is for JobScheduler enums inside the server directory. If you're
+// adding enums for app-side code, use the file in
+// frameworks/base/core/proto/android/app/job.
+option java_outer_classname = "JobServerProtoEnums";
+option java_multiple_files = true;
+
+// Set of constraints that a job potentially needs satisfied before it can run.
+// Defined in
+// frameworks/base/services/core/java/com/android/server/job/controllers/JobStatus.java
+enum ConstraintEnum {
+ CONSTRAINT_UNKNOWN = 0;
+ CONSTRAINT_CHARGING = 1;
+ CONSTRAINT_BATTERY_NOT_LOW = 2;
+ CONSTRAINT_STORAGE_NOT_LOW = 3;
+ CONSTRAINT_TIMING_DELAY = 4;
+ CONSTRAINT_DEADLINE = 5;
+ CONSTRAINT_IDLE = 6;
+ CONSTRAINT_CONNECTIVITY = 7;
+ CONSTRAINT_CONTENT_TRIGGER = 8;
+ CONSTRAINT_DEVICE_NOT_DOZING = 9;
+ CONSTRAINT_WITHIN_QUOTA = 10;
+ CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 11;
+}
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 188769d..6c9d13a 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -29,6 +29,7 @@
import "frameworks/base/core/proto/android/os/bundle.proto";
import "frameworks/base/core/proto/android/os/persistablebundle.proto";
import "frameworks/base/core/proto/android/server/forceappstandbytracker.proto";
+import "frameworks/base/core/proto/android/server/job/enums.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
// Next tag: 21
@@ -757,21 +758,9 @@
}
optional JobInfo job_info = 6;
- enum Constraint {
- CONSTRAINT_CHARGING = 1;
- CONSTRAINT_BATTERY_NOT_LOW = 2;
- CONSTRAINT_STORAGE_NOT_LOW = 3;
- CONSTRAINT_TIMING_DELAY = 4;
- CONSTRAINT_DEADLINE = 5;
- CONSTRAINT_IDLE = 6;
- CONSTRAINT_CONNECTIVITY = 7;
- CONSTRAINT_CONTENT_TRIGGER = 8;
- CONSTRAINT_DEVICE_NOT_DOZING = 9;
- CONSTRAINT_WITHIN_QUOTA = 10;
- }
- repeated Constraint required_constraints = 7;
- repeated Constraint satisfied_constraints = 8;
- repeated Constraint unsatisfied_constraints = 9;
+ repeated ConstraintEnum required_constraints = 7;
+ repeated ConstraintEnum satisfied_constraints = 8;
+ repeated ConstraintEnum unsatisfied_constraints = 9;
optional bool is_doze_whitelisted = 10;
optional bool is_uid_active = 26;
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 82bfa51..ed1a6d0 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -33,6 +33,7 @@
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
+import android.util.StatsLog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
@@ -40,6 +41,7 @@
import com.android.server.job.GrantedUriPermissions;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobServerProtoEnums;
import com.android.server.job.JobStatusDumpProto;
import com.android.server.job.JobStatusShortInfoProto;
@@ -80,6 +82,28 @@
static final int CONSTRAINT_WITHIN_QUOTA = 1 << 24;
static final int CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 1<<22;
+ /**
+ * The constraints that we want to log to statsd.
+ *
+ * Constraints that can be inferred from other atoms have been excluded to avoid logging too
+ * much information and to reduce redundancy:
+ *
+ * * CONSTRAINT_CHARGING can be inferred with PluggedStateChanged (Atom #32)
+ * * CONSTRAINT_BATTERY_NOT_LOW can be inferred with BatteryLevelChanged (Atom #30)
+ * * CONSTRAINT_CONNECTIVITY can be partially inferred with ConnectivityStateChanged
+ * (Atom #98) and BatterySaverModeStateChanged (Atom #20).
+ * * CONSTRAINT_DEVICE_NOT_DOZING can be mostly inferred with DeviceIdleModeStateChanged
+ * (Atom #21)
+ * * CONSTRAINT_BACKGROUND_NOT_RESTRICTED can be inferred with BatterySaverModeStateChanged
+ * (Atom #20)
+ */
+ private static final int STATSD_CONSTRAINTS_TO_LOG = CONSTRAINT_CONTENT_TRIGGER
+ | CONSTRAINT_DEADLINE
+ | CONSTRAINT_IDLE
+ | CONSTRAINT_STORAGE_NOT_LOW
+ | CONSTRAINT_TIMING_DELAY
+ | CONSTRAINT_WITHIN_QUOTA;
+
// Soft override: ignore constraints like time that don't affect API availability
public static final int OVERRIDE_SOFT = 1;
// Full override: ignore all constraints including API-affecting like connectivity
@@ -976,6 +1000,12 @@
}
satisfiedConstraints = (satisfiedConstraints&~constraint) | (state ? constraint : 0);
mSatisfiedConstraintsOfInterest = satisfiedConstraints & CONSTRAINTS_OF_INTEREST;
+ if ((STATSD_CONSTRAINTS_TO_LOG & constraint) != 0) {
+ StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED,
+ sourceUid, null, getBatteryName(), getProtoConstraint(constraint),
+ state ? StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__SATISFIED
+ : StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED);
+ }
return true;
}
@@ -1228,37 +1258,70 @@
}
}
+ /** Returns a {@link JobServerProtoEnums.Constraint} enum value for the given constraint. */
+ private int getProtoConstraint(int constraint) {
+ switch (constraint) {
+ case CONSTRAINT_BACKGROUND_NOT_RESTRICTED:
+ return JobServerProtoEnums.CONSTRAINT_BACKGROUND_NOT_RESTRICTED;
+ case CONSTRAINT_BATTERY_NOT_LOW:
+ return JobServerProtoEnums.CONSTRAINT_BATTERY_NOT_LOW;
+ case CONSTRAINT_CHARGING:
+ return JobServerProtoEnums.CONSTRAINT_CHARGING;
+ case CONSTRAINT_CONNECTIVITY:
+ return JobServerProtoEnums.CONSTRAINT_CONNECTIVITY;
+ case CONSTRAINT_CONTENT_TRIGGER:
+ return JobServerProtoEnums.CONSTRAINT_CONTENT_TRIGGER;
+ case CONSTRAINT_DEADLINE:
+ return JobServerProtoEnums.CONSTRAINT_DEADLINE;
+ case CONSTRAINT_DEVICE_NOT_DOZING:
+ return JobServerProtoEnums.CONSTRAINT_DEVICE_NOT_DOZING;
+ case CONSTRAINT_IDLE:
+ return JobServerProtoEnums.CONSTRAINT_IDLE;
+ case CONSTRAINT_STORAGE_NOT_LOW:
+ return JobServerProtoEnums.CONSTRAINT_STORAGE_NOT_LOW;
+ case CONSTRAINT_TIMING_DELAY:
+ return JobServerProtoEnums.CONSTRAINT_TIMING_DELAY;
+ case CONSTRAINT_WITHIN_QUOTA:
+ return JobServerProtoEnums.CONSTRAINT_WITHIN_QUOTA;
+ default:
+ return JobServerProtoEnums.CONSTRAINT_UNKNOWN;
+ }
+ }
+
/** Writes constraints to the given repeating proto field. */
void dumpConstraints(ProtoOutputStream proto, long fieldId, int constraints) {
if ((constraints & CONSTRAINT_CHARGING) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_CHARGING);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_CHARGING);
}
if ((constraints & CONSTRAINT_BATTERY_NOT_LOW) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_BATTERY_NOT_LOW);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_BATTERY_NOT_LOW);
}
if ((constraints & CONSTRAINT_STORAGE_NOT_LOW) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_STORAGE_NOT_LOW);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_STORAGE_NOT_LOW);
}
if ((constraints & CONSTRAINT_TIMING_DELAY) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_TIMING_DELAY);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_TIMING_DELAY);
}
if ((constraints & CONSTRAINT_DEADLINE) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_DEADLINE);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_DEADLINE);
}
if ((constraints & CONSTRAINT_IDLE) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_IDLE);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_IDLE);
}
if ((constraints & CONSTRAINT_CONNECTIVITY) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_CONNECTIVITY);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_CONNECTIVITY);
}
if ((constraints & CONSTRAINT_CONTENT_TRIGGER) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_CONTENT_TRIGGER);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_CONTENT_TRIGGER);
}
if ((constraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_DEVICE_NOT_DOZING);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_DEVICE_NOT_DOZING);
}
if ((constraints & CONSTRAINT_WITHIN_QUOTA) != 0) {
- proto.write(fieldId, JobStatusDumpProto.CONSTRAINT_WITHIN_QUOTA);
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_WITHIN_QUOTA);
+ }
+ if ((constraints & CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
+ proto.write(fieldId, JobServerProtoEnums.CONSTRAINT_BACKGROUND_NOT_RESTRICTED);
}
}