Merge "Store time until next interaction metric" into sc-dev
diff --git a/service/java/com/android/server/scheduling/RebootReadinessLogger.java b/service/java/com/android/server/scheduling/RebootReadinessLogger.java
index 1a10aae..61ed254 100644
--- a/service/java/com/android/server/scheduling/RebootReadinessLogger.java
+++ b/service/java/com/android/server/scheduling/RebootReadinessLogger.java
@@ -78,6 +78,9 @@
private int mTimesBlockedByAppActivity;
@GuardedBy("mLock")
+ private long mTimeUntilNextInteractionMs;
+
+ @GuardedBy("mLock")
private boolean mNeedsToLogMetrics;
@GuardedBy("mLock")
@@ -136,16 +139,7 @@
rebootStats.setTimesBlockedByInteractivity(timesBlockedByInteractivity);
rebootStats.setTimesBlockedBySubsystems(timesBlockedBySubsystems);
rebootStats.setTimesBlockedByAppActivity(timesBlockedByAppActivity);
- try (
- FileOutputStream stream = rebootStatsFile.startWrite()
- ) {
- XmlWriter writer = new XmlWriter(new PrintWriter(stream));
- XmlWriter.write(writer, rebootStats);
- writer.close();
- rebootStatsFile.finishWrite(stream);
- } catch (Exception e) {
- Log.e(TAG, "Could not write reboot readiness stats: " + e);
- }
+ writeRebootStatsToFile(rebootStats, rebootStatsFile);
}
}
@@ -164,6 +158,31 @@
}
/**
+ * Amend logging file when the device becomes not ready to reboot. If a logging file exists,
+ * add information about the time between the device becoming ready to reboot and subsequently
+ * not ready to reboot.
+ */
+ void writeAfterNotRebootReadyBroadcast() {
+ synchronized (mLock) {
+ AtomicFile rebootStatsFile = getRebootStatsFile();
+ if (rebootStatsFile != null) {
+ RebootStats rebootStats;
+ try (FileInputStream stream = rebootStatsFile.openRead()) {
+ rebootStats = XmlParser.read(stream);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not read reboot readiness stats: " + e);
+ return;
+ }
+
+ mTimeUntilNextInteractionMs = System.currentTimeMillis() - mReadyTime;
+ rebootStats.setTimeUntilNextInteractionMs(mTimeUntilNextInteractionMs);
+ writeRebootStatsToFile(rebootStats, rebootStatsFile);
+ }
+
+ }
+ }
+
+ /**
* If any metrics were stored before the last reboot, reads them into local variables. These
* local variables will be logged when the device is first unlocked after reboot.
*/
@@ -178,6 +197,9 @@
mTimesBlockedByInteractivity = rebootStats.getTimesBlockedByInteractivity();
mTimesBlockedBySubsystems = rebootStats.getTimesBlockedBySubsystems();
mTimesBlockedByAppActivity = rebootStats.getTimesBlockedByAppActivity();
+ if (rebootStats.hasTimeUntilNextInteractionMs()) {
+ mTimeUntilNextInteractionMs = rebootStats.getTimeUntilNextInteractionMs();
+ }
mNeedsToLogMetrics = true;
} catch (Exception e) {
Log.e(TAG, "Could not read reboot readiness stats: " + e);
@@ -198,18 +220,24 @@
mNeedsToLogMetrics = false;
long timeToUnlockMs = SystemClock.elapsedRealtime();
long timeToRebootReadyMs = mReadyTime - mStartTime;
+ long timeToNextInteractionMs = System.currentTimeMillis() - mReadyTime;
+ if (mTimeUntilNextInteractionMs != 0) {
+ timeToNextInteractionMs = mTimeUntilNextInteractionMs;
+ }
Log.i(TAG, "UnattendedRebootOccurred"
+ " rebootReadyMs=" + timeToRebootReadyMs
+ " timeUntilFirstUnlockMs=" + timeToUnlockMs
+ " blockedByInteractivity=" + mTimesBlockedByInteractivity
+ " blockedBySubsystems=" + mTimesBlockedBySubsystems
- + " blockedByAppActivity=" + mTimesBlockedByAppActivity);
+ + " blockedByAppActivity=" + mTimesBlockedByAppActivity
+ + " timeToNextInteractionMs=" + timeToNextInteractionMs);
SchedulingStatsLog.write(SchedulingStatsLog.UNATTENDED_REBOOT_OCCURRED,
timeToRebootReadyMs,
timeToUnlockMs,
mTimesBlockedByAppActivity,
mTimesBlockedBySubsystems,
- mTimesBlockedByInteractivity);
+ mTimesBlockedByInteractivity,
+ timeToNextInteractionMs);
mShouldDumpMetrics = true;
}
}
@@ -309,6 +337,17 @@
}
}
+ private void writeRebootStatsToFile(RebootStats rebootStats, AtomicFile rebootStatsFile) {
+ try (FileOutputStream stream = rebootStatsFile.startWrite()) {
+ XmlWriter writer = new XmlWriter(new PrintWriter(stream));
+ XmlWriter.write(writer, rebootStats);
+ writer.close();
+ rebootStatsFile.finishWrite(stream);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not write reboot readiness stats: " + e);
+ }
+ }
+
void dump(PrintWriter pw) {
synchronized (mLock) {
if (mBlockingComponents.size() > 0) {
@@ -326,6 +365,7 @@
pw.println(" Times blocked by interactivity " + mTimesBlockedByInteractivity);
pw.println(" Times blocked by subsystems " + mTimesBlockedBySubsystems);
pw.println(" Times blocked by app activity " + mTimesBlockedByAppActivity);
+ pw.println(" Time until next interaction " + mTimeUntilNextInteractionMs);
}
}
}
diff --git a/service/java/com/android/server/scheduling/RebootReadinessManagerService.java b/service/java/com/android/server/scheduling/RebootReadinessManagerService.java
index 94683e5..b480857 100644
--- a/service/java/com/android/server/scheduling/RebootReadinessManagerService.java
+++ b/service/java/com/android/server/scheduling/RebootReadinessManagerService.java
@@ -306,6 +306,11 @@
mHandler.removeCallbacksAndMessages(null);
mAlarmManager.cancel(mPollStateListener);
mCanceled = true;
+ // Delete any logging information if the device is ready to reboot, since an
+ // unattended reboot should not take place if the checks are cancelled.
+ if (mReadyToReboot) {
+ mRebootReadinessLogger.deleteLoggingInformation();
+ }
mReadyToReboot = false;
}
} else {
@@ -509,7 +514,7 @@
}
}
} else {
- mRebootReadinessLogger.deleteLoggingInformation();
+ mRebootReadinessLogger.writeAfterNotRebootReadyBroadcast();
}
}
}
diff --git a/service/reboot-stats-parser/Android.bp b/service/reboot-stats-parser/Android.bp
index 4962a84..c4703e7 100644
--- a/service/reboot-stats-parser/Android.bp
+++ b/service/reboot-stats-parser/Android.bp
@@ -20,5 +20,6 @@
name: "reboot-stats-parser",
srcs: ["reboot_stats_manifest.xsd"],
package_name: "com.android.server.scheduling",
+ api_dir: "schema",
gen_writer: true,
}
diff --git a/service/reboot-stats-parser/reboot_stats_manifest.xsd b/service/reboot-stats-parser/reboot_stats_manifest.xsd
index f416e39..39e0d4c 100644
--- a/service/reboot-stats-parser/reboot_stats_manifest.xsd
+++ b/service/reboot-stats-parser/reboot_stats_manifest.xsd
@@ -24,6 +24,7 @@
<xsd:element name="timesBlockedByInteractivity" type="xsd:int"/>
<xsd:element name="timesBlockedByAppActivity" type="xsd:int"/>
<xsd:element name="timesBlockedBySubsystems" type="xsd:int"/>
+ <xsd:element name="timeUntilNextInteractionMs" type="xsd:long"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
diff --git a/service/reboot-stats-parser/api/current.txt b/service/reboot-stats-parser/schema/current.txt
similarity index 92%
rename from service/reboot-stats-parser/api/current.txt
rename to service/reboot-stats-parser/schema/current.txt
index 75da6eb..f42ffb6 100644
--- a/service/reboot-stats-parser/api/current.txt
+++ b/service/reboot-stats-parser/schema/current.txt
@@ -5,11 +5,13 @@
ctor public RebootStats();
method public long getReadyTimeMs();
method public long getStartTimeMs();
+ method public long getTimeUntilNextInteractionMs();
method public int getTimesBlockedByAppActivity();
method public int getTimesBlockedByInteractivity();
method public int getTimesBlockedBySubsystems();
method public void setReadyTimeMs(long);
method public void setStartTimeMs(long);
+ method public void setTimeUntilNextInteractionMs(long);
method public void setTimesBlockedByAppActivity(int);
method public void setTimesBlockedByInteractivity(int);
method public void setTimesBlockedBySubsystems(int);
diff --git a/service/reboot-stats-parser/api/last_current.txt b/service/reboot-stats-parser/schema/last_current.txt
similarity index 100%
rename from service/reboot-stats-parser/api/last_current.txt
rename to service/reboot-stats-parser/schema/last_current.txt
diff --git a/service/reboot-stats-parser/api/last_removed.txt b/service/reboot-stats-parser/schema/last_removed.txt
similarity index 100%
rename from service/reboot-stats-parser/api/last_removed.txt
rename to service/reboot-stats-parser/schema/last_removed.txt
diff --git a/service/reboot-stats-parser/api/removed.txt b/service/reboot-stats-parser/schema/removed.txt
similarity index 100%
rename from service/reboot-stats-parser/api/removed.txt
rename to service/reboot-stats-parser/schema/removed.txt
diff --git a/tests/unittests/src/com/android/server/scheduling/RebootReadinessUnitTest.java b/tests/unittests/src/com/android/server/scheduling/RebootReadinessUnitTest.java
index b6da0ee..ff4c84c 100644
--- a/tests/unittests/src/com/android/server/scheduling/RebootReadinessUnitTest.java
+++ b/tests/unittests/src/com/android/server/scheduling/RebootReadinessUnitTest.java
@@ -30,7 +30,6 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -112,6 +111,9 @@
@Captor
private ArgumentCaptor<Integer> mIntCaptor;
+ @Captor
+ private ArgumentCaptor<Long> mLongCaptor;
+
private MockitoSession mSession;
@@ -425,14 +427,15 @@
mLogger.readMetricsPostReboot();
mLogger.writePostRebootMetrics();
verify(() -> SchedulingStatsLog.write(eq(SchedulingStatsLog.UNATTENDED_REBOOT_OCCURRED),
- eq(1000L), anyLong(), eq(0), eq(0), eq(0)));
+ eq(1000L), anyLong(), eq(0), eq(0), eq(0), anyLong()));
}
/**
- * Test that no metrics are logged if the device became not ready to reboot before rebooting.
+ * Test that logging information is correctly written in the case that the device becomes not
+ * ready to reboot.
*/
@Test
- public void testMetricsClearedWhenNotReadyToReboot() throws Exception {
+ public void testMetricsLoggedWhenNotReadyToReboot() throws Exception {
mService.markRebootPending(TEST_PACKAGE);
Thread.sleep(STATE_CHANGE_DELAY);
assertThat(mService.isReadyToReboot()).isTrue();
@@ -448,8 +451,13 @@
// The device has become not ready to reboot, therefore no metrics should be logged.
mLogger.readMetricsPostReboot();
mLogger.writePostRebootMetrics();
+
+ // Verify that the time_to_next_interaction_millis field is correctly populated.
verify(() -> SchedulingStatsLog.write(eq(SchedulingStatsLog.UNATTENDED_REBOOT_OCCURRED),
- anyLong(), anyLong(), anyInt(), anyInt(), anyInt()), never());
+ anyLong(), anyLong(), anyInt(), anyInt(),
+ anyInt(), mLongCaptor.capture()), times(1));
+ assertThat(mLongCaptor.getValue()).isGreaterThan(STATE_CHANGE_DELAY + DEVICE_CONFIG_DELAY);
+ assertThat(mLongCaptor.getValue()).isLessThan(TimeUnit.MINUTES.toMillis(1));
}
/**