diff --git a/api/current.txt b/api/current.txt index 9f4084c62eb84..421151a6080d5 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7360,8 +7360,8 @@ package android.app.usage { method public int getCount(); method public int getEventType(); method public long getFirstTimeStamp(); + method public long getLastEventTime(); method public long getLastTimeStamp(); - method public long getLastTimeUsed(); method public long getTotalTime(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -7469,6 +7469,8 @@ package android.app.usage { method public int getStandbyBucket(); method public long getTimeStamp(); field public static final int CONFIGURATION_CHANGE = 5; // 0x5 + field public static final int KEYGUARD_HIDDEN = 18; // 0x12 + field public static final int KEYGUARD_SHOWN = 17; // 0x11 field public static final int MOVE_TO_BACKGROUND = 2; // 0x2 field public static final int MOVE_TO_FOREGROUND = 1; // 0x1 field public static final int NONE = 0; // 0x0 diff --git a/core/java/android/app/usage/EventStats.java b/core/java/android/app/usage/EventStats.java index b799de9410a36..ea95a0557f2b6 100644 --- a/core/java/android/app/usage/EventStats.java +++ b/core/java/android/app/usage/EventStats.java @@ -41,10 +41,9 @@ public final class EventStats implements Parcelable { public long mEndTimeStamp; /** - * Last time used by the user with an explicit action (notification, activity launch). * {@hide} */ - public long mLastTimeUsed; + public long mLastEventTime; /** * {@hide} @@ -66,7 +65,7 @@ public final class EventStats implements Parcelable { mEventType = stats.mEventType; mBeginTimeStamp = stats.mBeginTimeStamp; mEndTimeStamp = stats.mEndTimeStamp; - mLastTimeUsed = stats.mLastTimeUsed; + mLastEventTime = stats.mLastEventTime; mTotalTime = stats.mTotalTime; mCount = stats.mCount; } @@ -100,12 +99,12 @@ public final class EventStats implements Parcelable { } /** - * Get the last time this event was used, measured in milliseconds since the epoch. + * Get the last time this event triggered, measured in milliseconds since the epoch. *

* See {@link System#currentTimeMillis()}. */ - public long getLastTimeUsed() { - return mLastTimeUsed; + public long getLastEventTime() { + return mLastEventTime; } /** @@ -138,7 +137,7 @@ public final class EventStats implements Parcelable { // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with // regards to their mEndTimeStamp. if (right.mBeginTimeStamp > mBeginTimeStamp) { - mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed); + mLastEventTime = Math.max(mLastEventTime, right.mLastEventTime); } mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp); mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp); @@ -156,7 +155,7 @@ public final class EventStats implements Parcelable { dest.writeInt(mEventType); dest.writeLong(mBeginTimeStamp); dest.writeLong(mEndTimeStamp); - dest.writeLong(mLastTimeUsed); + dest.writeLong(mLastEventTime); dest.writeLong(mTotalTime); dest.writeInt(mCount); } @@ -168,7 +167,7 @@ public final class EventStats implements Parcelable { stats.mEventType = in.readInt(); stats.mBeginTimeStamp = in.readLong(); stats.mEndTimeStamp = in.readLong(); - stats.mLastTimeUsed = in.readLong(); + stats.mLastEventTime = in.readLong(); stats.mTotalTime = in.readLong(); stats.mCount = in.readInt(); return stats; diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index a665652120009..84f57a301923a 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -152,6 +152,18 @@ public final class UsageEvents implements Parcelable { */ public static final int SCREEN_NON_INTERACTIVE = 16; + /** + * An event type denoting that the screen's keyguard has been shown, whether or not + * the screen is off. + */ + public static final int KEYGUARD_SHOWN = 17; + + /** + * An event type denoting that the screen's keyguard has been hidden. This typically + * happens when the user unlocks their phone after turning it on. + */ + public static final int KEYGUARD_HIDDEN = 18; + /** @hide */ public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0; diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index eafe91a3450a3..7fb97d3a0d22c 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -319,6 +319,8 @@ public final class UsageStatsManager { *

* *

The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS}

diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fd8998bce2dbb..e3e844a637389 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1529,6 +1529,11 @@ public class ActivityManagerService extends IActivityManager.Stub */ private int mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE; + /** + * State of external calls telling us if the device is awake or asleep. + */ + private boolean mKeyguardShown = false; + /** * Set if we are shutting down the system, similar to sleeping. */ @@ -13094,6 +13099,12 @@ public class ActivityManagerService extends IActivityManager.Stub : UsageEvents.Event.SCREEN_NON_INTERACTIVE); } + void reportCurKeyguardUsageEventLocked() { + reportGlobalUsageEventLocked(mKeyguardShown + ? UsageEvents.Event.KEYGUARD_SHOWN + : UsageEvents.Event.KEYGUARD_HIDDEN); + } + void onWakefulnessChanged(int wakefulness) { synchronized(this) { boolean wasAwake = mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE; @@ -13257,6 +13268,10 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized(this) { long ident = Binder.clearCallingIdentity(); + if (mKeyguardShown != keyguardShowing) { + mKeyguardShown = keyguardShowing; + reportCurKeyguardUsageEventLocked(); + } try { mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing, secondaryDisplayShowing); diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index f710690fbd2f1..a2943346e0749 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -1593,6 +1593,7 @@ class UserController implements Handler.Callback { void onSystemReady() { updateCurrentProfileIds(); + mInjector.reportCurWakefulnessUsageEvent(); } /** diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java index b070e03607cb6..c914689183b13 100644 --- a/services/usage/java/com/android/server/usage/IntervalStats.java +++ b/services/usage/java/com/android/server/usage/IntervalStats.java @@ -30,12 +30,10 @@ class IntervalStats { public long beginTime; public long endTime; public long lastTimeSaved; - public long lastInteractiveTime; - public long lastNonInteractiveTime; - public long interactiveDuration; - public int interactiveCount; - public long nonInteractiveDuration; - public int nonInteractiveCount; + public final EventTracker interactiveTracker = new EventTracker(); + public final EventTracker nonInteractiveTracker = new EventTracker(); + public final EventTracker keyguardShownTracker = new EventTracker(); + public final EventTracker keyguardHiddenTracker = new EventTracker(); public final ArrayMap packageStats = new ArrayMap<>(); public final ArrayMap configurations = new ArrayMap<>(); public Configuration activeConfiguration; @@ -47,6 +45,44 @@ class IntervalStats { // strings that had identical copies in the cache. private final ArraySet mStringCache = new ArraySet<>(); + public static final class EventTracker { + public long curStartTime; + public long lastEventTime; + public long duration; + public int count; + + public void commitTime(long timeStamp) { + if (curStartTime != 0) { + duration += timeStamp - duration; + curStartTime = 0; + } + } + + public void update(long timeStamp) { + if (curStartTime == 0) { + // If we aren't already running, time to bump the count. + count++; + } + commitTime(timeStamp); + curStartTime = timeStamp; + lastEventTime = timeStamp; + } + + void addToEventStats(List out, int event, long beginTime, long endTime) { + if (count != 0 || duration != 0) { + EventStats ev = new EventStats(); + ev.mEventType = event; + ev.mCount = count; + ev.mTotalTime = duration; + ev.mLastEventTime = lastEventTime; + ev.mBeginTimeStamp = beginTime; + ev.mEndTimeStamp = endTime; + out.add(ev); + } + } + + } + /** * Gets the UsageStats object for the given package, or creates one and adds it internally. */ @@ -180,58 +216,42 @@ class IntervalStats { usageStats.mAppLaunchCount += 1; } - private void commitInteractiveTime(long timeStamp) { - if (lastInteractiveTime != 0) { - interactiveDuration += timeStamp - lastInteractiveTime; - lastInteractiveTime = 0; - } - if (lastNonInteractiveTime != 0) { - nonInteractiveDuration += timeStamp - lastNonInteractiveTime; - lastNonInteractiveTime = 0; - } - } - void commitTime(long timeStamp) { - commitInteractiveTime(timeStamp); + interactiveTracker.commitTime(timeStamp); + nonInteractiveTracker.commitTime(timeStamp); + keyguardShownTracker.commitTime(timeStamp); + keyguardHiddenTracker.commitTime(timeStamp); } void updateScreenInteractive(long timeStamp) { - if (lastInteractiveTime != 0) { - // Already interactive, just keep running. - return; - } - commitInteractiveTime(timeStamp); - lastInteractiveTime = timeStamp; - interactiveCount++; + interactiveTracker.update(timeStamp); + nonInteractiveTracker.commitTime(timeStamp); } void updateScreenNonInteractive(long timeStamp) { - if (lastNonInteractiveTime != 0) { - // Already non-interactive, just keep running. - return; - } - commitInteractiveTime(timeStamp); - lastNonInteractiveTime = timeStamp; - nonInteractiveCount++; + nonInteractiveTracker.update(timeStamp); + interactiveTracker.commitTime(timeStamp); } - private void addOneEventStats(List out, int event, int count, long duration) { - if (count != 0 || duration != 0) { - EventStats ev = new EventStats(); - ev.mEventType = event; - ev.mCount = count; - ev.mTotalTime = duration; - ev.mBeginTimeStamp = beginTime; - ev.mEndTimeStamp = endTime; - out.add(ev); - } + void updateKeyguardShown(long timeStamp) { + keyguardShownTracker.update(timeStamp); + keyguardHiddenTracker.commitTime(timeStamp); + } + + void updateKeyguardHidden(long timeStamp) { + keyguardHiddenTracker.update(timeStamp); + keyguardShownTracker.commitTime(timeStamp); } void addEventStatsTo(List out) { - addOneEventStats(out, UsageEvents.Event.SCREEN_INTERACTIVE, interactiveCount, - interactiveDuration); - addOneEventStats(out, UsageEvents.Event.SCREEN_NON_INTERACTIVE, nonInteractiveCount, - nonInteractiveDuration); + interactiveTracker.addToEventStats(out, UsageEvents.Event.SCREEN_INTERACTIVE, + beginTime, endTime); + nonInteractiveTracker.addToEventStats(out, UsageEvents.Event.SCREEN_NON_INTERACTIVE, + beginTime, endTime); + keyguardShownTracker.addToEventStats(out, UsageEvents.Event.KEYGUARD_SHOWN, + beginTime, endTime); + keyguardHiddenTracker.addToEventStats(out, UsageEvents.Event.KEYGUARD_HIDDEN, + beginTime, endTime); } private String getCachedStringRef(String str) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java index 2287b2770f457..fe3a8845b3a3f 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java +++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java @@ -40,6 +40,8 @@ final class UsageStatsXmlV1 { private static final String INTERACTIVE_TAG = "interactive"; private static final String NON_INTERACTIVE_TAG = "non-interactive"; + private static final String KEYGUARD_SHOWN_TAG = "keyguard-shown"; + private static final String KEYGUARD_HIDDEN_TAG = "keyguard-hidden"; private static final String PACKAGES_TAG = "packages"; private static final String PACKAGE_TAG = "package"; @@ -103,12 +105,12 @@ final class UsageStatsXmlV1 { } } - private static Pair loadCountAndTime(XmlPullParser parser) + private static void loadCountAndTime(XmlPullParser parser, + IntervalStats.EventTracker tracker) throws IOException, XmlPullParserException { - int count = XmlUtils.readIntAttribute(parser, COUNT_ATTR, 0); - long time = XmlUtils.readLongAttribute(parser, TIME_ATTR, 0); + tracker.count = XmlUtils.readIntAttribute(parser, COUNT_ATTR, 0); + tracker.duration = XmlUtils.readLongAttribute(parser, TIME_ATTR, 0); XmlUtils.skipCurrentTag(parser); - return new Pair<>(count, time); } private static void loadChooserCounts( @@ -340,17 +342,21 @@ final class UsageStatsXmlV1 { final String tag = parser.getName(); switch (tag) { - case INTERACTIVE_TAG: { - Pair result = loadCountAndTime(parser); - statsOut.interactiveCount = result.first; - statsOut.interactiveDuration = result.second; - } break; + case INTERACTIVE_TAG: + loadCountAndTime(parser, statsOut.interactiveTracker); + break; - case NON_INTERACTIVE_TAG: { - Pair result = loadCountAndTime(parser); - statsOut.nonInteractiveCount = result.first; - statsOut.nonInteractiveDuration = result.second; - } break; + case NON_INTERACTIVE_TAG: + loadCountAndTime(parser, statsOut.nonInteractiveTracker); + break; + + case KEYGUARD_SHOWN_TAG: + loadCountAndTime(parser, statsOut.keyguardShownTracker); + break; + + case KEYGUARD_HIDDEN_TAG: + loadCountAndTime(parser, statsOut.keyguardHiddenTracker); + break; case PACKAGE_TAG: loadUsageStats(parser, statsOut); @@ -378,10 +384,14 @@ final class UsageStatsXmlV1 { public static void write(XmlSerializer xml, IntervalStats stats) throws IOException { XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime); - writeCountAndTime(xml, INTERACTIVE_TAG, stats.interactiveCount, stats.interactiveDuration); - - writeCountAndTime(xml, NON_INTERACTIVE_TAG, stats.nonInteractiveCount, - stats.nonInteractiveDuration); + writeCountAndTime(xml, INTERACTIVE_TAG, stats.interactiveTracker.count, + stats.interactiveTracker.duration); + writeCountAndTime(xml, NON_INTERACTIVE_TAG, stats.nonInteractiveTracker.count, + stats.nonInteractiveTracker.duration); + writeCountAndTime(xml, KEYGUARD_SHOWN_TAG, stats.keyguardShownTracker.count, + stats.keyguardShownTracker.duration); + writeCountAndTime(xml, KEYGUARD_HIDDEN_TAG, stats.keyguardHiddenTracker.count, + stats.keyguardHiddenTracker.duration); xml.startTag(null, PACKAGES_TAG); final int statsCount = stats.packageStats.size(); diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 6ad374bc42905..d9fc066f2402e 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -211,6 +211,12 @@ class UserUsageStatsService { case UsageEvents.Event.SCREEN_NON_INTERACTIVE: { stats.updateScreenNonInteractive(event.mTimeStamp); } break; + case UsageEvents.Event.KEYGUARD_SHOWN: { + stats.updateKeyguardShown(event.mTimeStamp); + } break; + case UsageEvents.Event.KEYGUARD_HIDDEN: { + stats.updateKeyguardHidden(event.mTimeStamp); + } break; default: { stats.update(event.mPackage, event.mTimeStamp, event.mEventType); if (incrementAppLaunch) { @@ -665,14 +671,19 @@ class UserUsageStatsService { } } - void printEventAggregation(IndentingPrintWriter pw, String label, int count, long duration, - boolean prettyDates) { - if (count != 0 || duration != 0) { + void printEventAggregation(IndentingPrintWriter pw, String label, + IntervalStats.EventTracker tracker, boolean prettyDates) { + if (tracker.count != 0 || tracker.duration != 0) { pw.print(label); pw.print(": "); - pw.print(count); + pw.print(tracker.count); pw.print("x for "); - pw.print(formatElapsedTime(duration, prettyDates)); + pw.print(formatElapsedTime(tracker.duration, prettyDates)); + if (tracker.curStartTime != 0) { + pw.print(" (now running, started at "); + formatDateTime(tracker.curStartTime, prettyDates); + pw.print(")"); + } pw.println(); } } @@ -752,10 +763,14 @@ class UserUsageStatsService { pw.decreaseIndent(); pw.println("event aggregations"); pw.increaseIndent(); - printEventAggregation(pw, "screen-interactive", stats.interactiveCount, - stats.interactiveDuration, prettyDates); - printEventAggregation(pw, "screen-non-interactive", stats.nonInteractiveCount, - stats.nonInteractiveDuration, prettyDates); + printEventAggregation(pw, "screen-interactive", stats.interactiveTracker, + prettyDates); + printEventAggregation(pw, "screen-non-interactive", stats.nonInteractiveTracker, + prettyDates); + printEventAggregation(pw, "keyguard-shown", stats.keyguardShownTracker, + prettyDates); + printEventAggregation(pw, "keyguard-hidden", stats.keyguardHiddenTracker, + prettyDates); pw.decreaseIndent(); }