UsageStats: Change INTERACTION to SYSTEM_INTERACTION
SYSTEM_INTERACTION events are signals to the system for a package's
implicit actions (service bound, etc).
These should not affect the API visible stats like lastTimeUsed, etc.
USER_INTERACTION is for user initiated actions (notification interaction, etc).
Bug:21761781
Change-Id: I4585cf35fbb158612a3c737710108bec34e89183
diff --git a/api/current.txt b/api/current.txt
index 058297a..24ad077 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6148,10 +6148,10 @@
method public java.lang.String getPackageName();
method public long getTimeStamp();
field public static final int CONFIGURATION_CHANGE = 5; // 0x5
- field public static final int INTERACTION = 6; // 0x6
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
+ field public static final int USER_INTERACTION = 7; // 0x7
}
public final class UsageStats implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index ea2de6b..0d10c43 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6341,10 +6341,10 @@
method public java.lang.String getPackageName();
method public long getTimeStamp();
field public static final int CONFIGURATION_CHANGE = 5; // 0x5
- field public static final int INTERACTION = 6; // 0x6
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
+ field public static final int USER_INTERACTION = 7; // 0x7
}
public final class UsageStats implements android.os.Parcelable {
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 58279d7..369b692 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -68,9 +68,15 @@
public static final int CONFIGURATION_CHANGE = 5;
/**
- * An event type denoting that a package was interacted with in some way.
+ * An event type denoting that a package was interacted with in some way by the system.
+ * @hide
*/
- public static final int INTERACTION = 6;
+ public static final int SYSTEM_INTERACTION = 6;
+
+ /**
+ * An event type denoting that a package was interacted with in some way by the user.
+ */
+ public static final int USER_INTERACTION = 7;
/**
* {@hide}
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 81c7422..0fce4e2 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -41,11 +41,19 @@
public long mEndTimeStamp;
/**
+ * Last time used by the user with an explicit action (notification, activity launch).
* {@hide}
*/
public long mLastTimeUsed;
/**
+ * The last time the package was used via implicit, non-user initiated actions (service
+ * was bound, etc).
+ * {@hide}
+ */
+ public long mLastTimeSystemUsed;
+
+ /**
* Last time the package was used and the beginning of the idle countdown.
* This uses a different timebase that is about how much the device has been in use in general.
* {@hide}
@@ -82,6 +90,7 @@
mLaunchCount = stats.mLaunchCount;
mLastEvent = stats.mLastEvent;
mBeginIdleTime = stats.mBeginIdleTime;
+ mLastTimeSystemUsed = stats.mLastTimeSystemUsed;
}
public String getPackageName() {
@@ -119,6 +128,16 @@
/**
* @hide
+ * Get the last time this package was used by the system (not the user). This can be different
+ * from {@link #getLastTimeUsed()} when the system binds to one of this package's services.
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeSystemUsed() {
+ return mLastTimeSystemUsed;
+ }
+
+ /**
+ * @hide
* Get the last time this package was active, measured in milliseconds. This timestamp
* uses a timebase that represents how much the device was used and not wallclock time.
*/
@@ -151,6 +170,7 @@
mEndTimeStamp = right.mEndTimeStamp;
mLastTimeUsed = right.mLastTimeUsed;
mBeginIdleTime = right.mBeginIdleTime;
+ mLastTimeSystemUsed = right.mLastTimeSystemUsed;
}
mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
mTotalTimeInForeground += right.mTotalTimeInForeground;
@@ -172,6 +192,7 @@
dest.writeInt(mLaunchCount);
dest.writeInt(mLastEvent);
dest.writeLong(mBeginIdleTime);
+ dest.writeLong(mLastTimeSystemUsed);
}
public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -186,6 +207,7 @@
stats.mLaunchCount = in.readInt();
stats.mLastEvent = in.readInt();
stats.mBeginIdleTime = in.readLong();
+ stats.mLastTimeSystemUsed = in.readLong();
return stats;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0d08c2a..d974de0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18617,7 +18617,7 @@
if (packages != null) {
for (int i = 0; i < packages.length; i++) {
mUsageStatsService.reportEvent(packages[i], app.userId,
- UsageEvents.Event.INTERACTION);
+ UsageEvents.Event.SYSTEM_INTERACTION);
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8ee2076..90e912d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1407,7 +1407,7 @@
mAppUsageStats.reportEvent(r.sbn.getPackageName(),
userId == UserHandle.USER_ALL ? UserHandle.USER_OWNER
: userId,
- UsageEvents.Event.INTERACTION);
+ UsageEvents.Event.USER_INTERACTION);
r.setSeen();
}
}
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index a615675..1aa2978 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -110,7 +110,10 @@
usageStats.mLastEvent = eventType;
}
- usageStats.mLastTimeUsed = timeStamp;
+ if (eventType != UsageEvents.Event.SYSTEM_INTERACTION) {
+ usageStats.mLastTimeUsed = timeStamp;
+ }
+ usageStats.mLastTimeSystemUsed = timeStamp;
usageStats.mEndTimeStamp = timeStamp;
if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
@@ -131,9 +134,9 @@
usageStats.mBeginIdleTime = timeStamp;
}
- void updateLastUsedTime(String packageName, long lastUsedTime) {
+ void updateSystemLastUsedTime(String packageName, long lastUsedTime) {
UsageStats usageStats = getOrCreateUsageStats(packageName);
- usageStats.mLastTimeUsed = lastUsedTime;
+ usageStats.mLastTimeSystemUsed = lastUsedTime;
}
void updateConfigurationStats(Configuration config, long timeStamp) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 633aee8..7a34757 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -60,7 +60,6 @@
import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.util.AtomicFile;
-import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -543,14 +542,15 @@
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
final long beginIdleTime = service.getBeginIdleTime(event.mPackage);
- final long lastUsedTime = service.getLastUsedTime(event.mPackage);
+ final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage);
final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
lastUsedTime, screenOnTime, timeNow);
service.reportEvent(event, getScreenOnTimeLocked(timeNow));
// Inform listeners if necessary
if ((event.mEventType == Event.MOVE_TO_FOREGROUND
|| event.mEventType == Event.MOVE_TO_BACKGROUND
- || event.mEventType == Event.INTERACTION)) {
+ || event.mEventType == Event.SYSTEM_INTERACTION
+ || event.mEventType == Event.USER_INTERACTION)) {
if (previouslyIdle) {
// Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
@@ -575,11 +575,11 @@
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
final long beginIdleTime = service.getBeginIdleTime(packageName);
- final long lastUsedTime = service.getLastUsedTime(packageName);
+ final long lastUsedTime = service.getSystemLastUsedTime(packageName);
final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
lastUsedTime, screenOnTime, timeNow);
service.setBeginIdleTime(packageName, deviceUsageTime);
- service.setLastUsedTime(packageName,
+ service.setSystemLastUsedTime(packageName,
timeNow - (idle ? DEFAULT_WALLCLOCK_APP_IDLE_THRESHOLD_MILLIS : 0) - 5000);
// Inform listeners if necessary
if (previouslyIdle != idle) {
@@ -666,7 +666,7 @@
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
long beginIdleTime = service.getBeginIdleTime(packageName);
- long lastUsedTime = service.getLastUsedTime(packageName);
+ long lastUsedTime = service.getSystemLastUsedTime(packageName);
return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow);
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 0111201..f2ca3a4 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -55,6 +55,7 @@
// Time attributes stored as an offset of the beginTime.
private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+ private static final String LAST_TIME_ACTIVE_SYSTEM_ATTR = "lastTimeActiveSystem";
private static final String BEGIN_IDLE_TIME_ATTR = "beginIdleTime";
private static final String END_TIME_ATTR = "endTime";
private static final String TIME_ATTR = "time";
@@ -71,6 +72,16 @@
// Apply the offset to the beginTime to find the absolute time.
stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
parser, LAST_TIME_ACTIVE_ATTR);
+
+ final String lastTimeUsedSystem = parser.getAttributeValue(null,
+ LAST_TIME_ACTIVE_SYSTEM_ATTR);
+ if (TextUtils.isEmpty(lastTimeUsedSystem)) {
+ // If the field isn't present, use the old one.
+ stats.mLastTimeSystemUsed = stats.mLastTimeUsed;
+ } else {
+ stats.mLastTimeSystemUsed = statsOut.beginTime + Long.parseLong(lastTimeUsedSystem);
+ }
+
final String beginIdleTime = parser.getAttributeValue(null, BEGIN_IDLE_TIME_ATTR);
if (!TextUtils.isEmpty(beginIdleTime)) {
stats.mBeginIdleTime = Long.parseLong(beginIdleTime);
@@ -130,6 +141,8 @@
// Write the time offset.
XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
usageStats.mLastTimeUsed - stats.beginTime);
+ XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_SYSTEM_ATTR,
+ usageStats.mLastTimeSystemUsed - stats.beginTime);
XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 7c00dae..b07b815 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -157,7 +157,7 @@
if (pi.applicationInfo != null && (firstUpdate || pi.applicationInfo.isSystemApp())
&& getBeginIdleTime(packageName) == -1) {
for (IntervalStats stats : mCurrentStats) {
- stats.update(packageName, currentTimeMillis, Event.INTERACTION);
+ stats.update(packageName, currentTimeMillis, Event.SYSTEM_INTERACTION);
stats.updateBeginIdleTime(packageName, deviceUsageTime);
mStatsChanged = true;
}
@@ -199,7 +199,7 @@
if (currentDailyStats.events == null) {
currentDailyStats.events = new TimeSparseArray<>();
}
- if (event.mEventType != UsageEvents.Event.INTERACTION) {
+ if (event.mEventType != UsageEvents.Event.SYSTEM_INTERACTION) {
currentDailyStats.events.put(event.mTimeStamp, event);
}
@@ -226,9 +226,9 @@
notifyStatsChanged();
}
- void setLastUsedTime(String packageName, long lastUsedTime) {
+ void setSystemLastUsedTime(String packageName, long lastUsedTime) {
for (IntervalStats stats : mCurrentStats) {
- stats.updateLastUsedTime(packageName, lastUsedTime);
+ stats.updateSystemLastUsedTime(packageName, lastUsedTime);
}
notifyStatsChanged();
}
@@ -397,13 +397,13 @@
}
}
- long getLastUsedTime(String packageName) {
+ long getSystemLastUsedTime(String packageName) {
final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY];
UsageStats packageUsage;
if ((packageUsage = yearly.packageStats.get(packageName)) == null) {
return -1;
} else {
- return packageUsage.getLastTimeUsed();
+ return packageUsage.getLastTimeSystemUsed();
}
}
@@ -586,8 +586,11 @@
for (int i = 0; i < pkgCount; i++) {
final UsageStats usageStats = pkgStats.valueAt(i);
pw.printPair("package", usageStats.mPackageName);
- pw.printPair("totalTime", formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates));
+ pw.printPair("totalTime",
+ formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates));
pw.printPair("lastTime", formatDateTime(usageStats.mLastTimeUsed, prettyDates));
+ pw.printPair("lastTimeSystem",
+ formatDateTime(usageStats.mLastTimeSystemUsed, prettyDates));
pw.printPair("inactiveTime",
formatElapsedTime(screenOnTime - usageStats.mBeginIdleTime, prettyDates));
pw.println();
@@ -596,8 +599,7 @@
pw.println("configurations");
pw.increaseIndent();
- final ArrayMap<Configuration, ConfigurationStats> configStats =
- stats.configurations;
+ final ArrayMap<Configuration, ConfigurationStats> configStats = stats.configurations;
final int configCount = configStats.size();
for (int i = 0; i < configCount; i++) {
final ConfigurationStats config = configStats.valueAt(i);
@@ -659,8 +661,10 @@
return "CONTINUE_PREVIOUS_DAY";
case UsageEvents.Event.CONFIGURATION_CHANGE:
return "CONFIGURATION_CHANGE";
- case UsageEvents.Event.INTERACTION:
- return "INTERACTION";
+ case UsageEvents.Event.SYSTEM_INTERACTION:
+ return "SYSTEM_INTERACTION";
+ case UsageEvents.Event.USER_INTERACTION:
+ return "USER_INTERACTION";
default:
return "UNKNOWN";
}
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
index 8e6daea..05cac10 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
@@ -28,8 +28,6 @@
import android.widget.BaseAdapter;
import android.widget.TextView;
-import java.util.ArrayList;
-
public class UsageLogActivity extends ListActivity implements Runnable {
private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
@@ -166,8 +164,8 @@
case UsageEvents.Event.CONFIGURATION_CHANGE:
return "Config change";
- case UsageEvents.Event.INTERACTION:
- return "Interaction";
+ case UsageEvents.Event.USER_INTERACTION:
+ return "User Interaction";
default:
return "Unknown: " + eventType;