summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManager.java14
-rw-r--r--core/java/android/app/AppOpsManager.java11
-rw-r--r--core/java/android/app/ContextImpl.java5
-rw-r--r--core/java/android/app/UsageStats.aidl20
-rw-r--r--core/java/android/app/UsageStats.java406
-rw-r--r--core/java/android/app/UsageStatsManager.java51
-rw-r--r--core/java/android/content/Context.java10
-rw-r--r--core/java/android/os/ParcelableParcel.aidl19
8 files changed, 528 insertions, 8 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5d809d8..044727d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -20,7 +20,6 @@ import android.os.BatteryStats;
import android.os.IBinder;
import com.android.internal.app.IUsageStats;
import com.android.internal.app.ProcessStats;
-import com.android.internal.os.PkgUsageStats;
import com.android.internal.os.TransferPipe;
import com.android.internal.util.FastPrintWriter;
@@ -2130,14 +2129,15 @@ public class ActivityManager {
return new HashMap<String, Integer>();
}
- PkgUsageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats();
+ UsageStats.PackageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats(
+ ActivityThread.currentPackageName());
if (allPkgUsageStats == null) {
return new HashMap<String, Integer>();
}
Map<String, Integer> launchCounts = new HashMap<String, Integer>();
- for (PkgUsageStats pkgUsageStats : allPkgUsageStats) {
- launchCounts.put(pkgUsageStats.packageName, pkgUsageStats.launchCount);
+ for (UsageStats.PackageStats pkgUsageStats : allPkgUsageStats) {
+ launchCounts.put(pkgUsageStats.getPackageName(), pkgUsageStats.getLaunchCount());
}
return launchCounts;
@@ -2251,17 +2251,17 @@ public class ActivityManager {
*
* @hide
*/
- public PkgUsageStats[] getAllPackageUsageStats() {
+ public UsageStats.PackageStats[] getAllPackageUsageStats() {
try {
IUsageStats usageStatsService = IUsageStats.Stub.asInterface(
ServiceManager.getService("usagestats"));
if (usageStatsService != null) {
- return usageStatsService.getAllPkgUsageStats();
+ return usageStatsService.getAllPkgUsageStats(ActivityThread.currentPackageName());
}
} catch (RemoteException e) {
Log.w(TAG, "Could not query usage stats", e);
}
- return new PkgUsageStats[0];
+ return new UsageStats.PackageStats[0];
}
/**
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index b616c1e..d813dab 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.Manifest;
import android.os.Binder;
import android.os.IBinder;
import android.util.ArrayMap;
@@ -184,8 +185,10 @@ public class AppOpsManager {
public static final int OP_MONITOR_LOCATION = 41;
/** @hide Continually monitoring location data with a relatively high power request. */
public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
+ /** @hide Retrieve current usage stats via {@link UsageStatsManager}. */
+ public static final int OP_GET_USAGE_STATS = 43;
/** @hide */
- public static final int _NUM_OP = 43;
+ public static final int _NUM_OP = 44;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION =
@@ -252,6 +255,7 @@ public class AppOpsManager {
OP_WAKE_LOCK,
OP_COARSE_LOCATION,
OP_COARSE_LOCATION,
+ OP_GET_USAGE_STATS,
};
/**
@@ -302,6 +306,7 @@ public class AppOpsManager {
null,
OPSTR_MONITOR_LOCATION,
OPSTR_MONITOR_HIGH_POWER_LOCATION,
+ null,
};
/**
@@ -352,6 +357,7 @@ public class AppOpsManager {
"WAKE_LOCK",
"MONITOR_LOCATION",
"MONITOR_HIGH_POWER_LOCATION",
+ "GET_USAGE_STATS"
};
/**
@@ -402,6 +408,7 @@ public class AppOpsManager {
android.Manifest.permission.WAKE_LOCK,
null, // no permission for generic location monitoring
null, // no permission for high power location monitoring
+ android.Manifest.permission.PACKAGE_USAGE_STATS,
};
/**
@@ -451,6 +458,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
+ AppOpsManager.MODE_IGNORED, // OP_GET_USAGE_STATS
};
/**
@@ -504,6 +512,7 @@ public class AppOpsManager {
false,
false,
false,
+ false,
};
private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5ed5030..801182d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -678,6 +678,11 @@ class ContextImpl extends Context {
return new NetworkScoreManager(ctx);
}
});
+
+ registerService(USAGE_STATS_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ return new UsageStatsManager(ctx.getOuterContext());
+ }});
}
static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/app/UsageStats.aidl b/core/java/android/app/UsageStats.aidl
new file mode 100644
index 0000000..7dee70a
--- /dev/null
+++ b/core/java/android/app/UsageStats.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2014, 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.
+ */
+
+package android.app;
+
+parcelable UsageStats;
+parcelable UsageStats.PackageStats;
diff --git a/core/java/android/app/UsageStats.java b/core/java/android/app/UsageStats.java
new file mode 100644
index 0000000..0aeba59
--- /dev/null
+++ b/core/java/android/app/UsageStats.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package android.app;
+
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * Snapshot of current usage stats data.
+ * @hide
+ */
+public class UsageStats implements Parcelable {
+ /** @hide */
+ public final ArrayMap<String, PackageStats> mPackages = new ArrayMap<String, PackageStats>();
+ /** @hide */
+ public final ArrayMap<Configuration, ConfigurationStats> mConfigurations
+ = new ArrayMap<Configuration, ConfigurationStats>();
+
+ public static class PackageStats implements Parcelable {
+ private final String mPackageName;
+ private int mLaunchCount;
+ private long mUsageTime;
+ private long mResumedTime;
+
+ /** @hide */
+ public final ArrayMap<String, Long> componentResumeTimes;
+
+ public static final Parcelable.Creator<PackageStats> CREATOR
+ = new Parcelable.Creator<PackageStats>() {
+ public PackageStats createFromParcel(Parcel in) {
+ return new PackageStats(in);
+ }
+
+ public PackageStats[] newArray(int size) {
+ return new PackageStats[size];
+ }
+ };
+
+ public String toString() {
+ return "PackageStats{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " " + mPackageName + "}";
+ }
+
+ /** @hide */
+ public PackageStats(String pkgName) {
+ mPackageName = pkgName;
+ componentResumeTimes = new ArrayMap<String, Long>();
+ }
+
+ /** @hide */
+ public PackageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
+ mPackageName = pkgName;
+ mLaunchCount = count;
+ mUsageTime = time;
+ componentResumeTimes = new ArrayMap<String, Long>();
+ componentResumeTimes.putAll(lastResumeTimes);
+ }
+
+ /** @hide */
+ public PackageStats(Parcel source) {
+ mPackageName = source.readString();
+ mLaunchCount = source.readInt();
+ mUsageTime = source.readLong();
+ final int N = source.readInt();
+ componentResumeTimes = new ArrayMap<String, Long>(N);
+ for (int i = 0; i < N; i++) {
+ String component = source.readString();
+ long lastResumeTime = source.readLong();
+ componentResumeTimes.put(component, lastResumeTime);
+ }
+ }
+
+ /** @hide */
+ public PackageStats(PackageStats pStats) {
+ mPackageName = pStats.mPackageName;
+ mLaunchCount = pStats.mLaunchCount;
+ mUsageTime = pStats.mUsageTime;
+ componentResumeTimes = new ArrayMap<String, Long>(pStats.componentResumeTimes);
+ }
+
+ /** @hide */
+ public void resume(boolean launched) {
+ if (launched) {
+ mLaunchCount++;
+ }
+ mResumedTime = SystemClock.elapsedRealtime();
+ }
+
+ /** @hide */
+ public void pause() {
+ if (mResumedTime > 0) {
+ mUsageTime += SystemClock.elapsedRealtime() - mResumedTime;
+ }
+ mResumedTime = 0;
+ }
+
+ public final String getPackageName() {
+ return mPackageName;
+ }
+
+ public final long getUsageTime(long elapsedRealtime) {
+ return mUsageTime + (mResumedTime > 0 ? (elapsedRealtime- mResumedTime) : 0);
+ }
+
+ public final int getLaunchCount() {
+ return mLaunchCount;
+ }
+
+ /** @hide */
+ public boolean clearUsageTimes() {
+ mLaunchCount = 0;
+ mUsageTime = 0;
+ return mResumedTime <= 0 && componentResumeTimes.isEmpty();
+ }
+
+ public final int describeContents() {
+ return 0;
+ }
+
+ public final void writeToParcel(Parcel dest, int parcelableFlags) {
+ writeToParcel(dest, parcelableFlags, 0);
+ }
+
+ final void writeToParcel(Parcel dest, int parcelableFlags, long elapsedRealtime) {
+ dest.writeString(mPackageName);
+ dest.writeInt(mLaunchCount);
+ dest.writeLong(elapsedRealtime > 0 ? getUsageTime(elapsedRealtime) : mUsageTime);
+ dest.writeInt(componentResumeTimes.size());
+ for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
+ dest.writeString(ent.getKey());
+ dest.writeLong(ent.getValue());
+ }
+ }
+
+ /** @hide */
+ public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+ }
+ }
+
+ public static class ConfigurationStats implements Parcelable {
+ private final Configuration mConfiguration;
+ private long mLastUsedTime;
+ private int mUsageCount;
+ private long mUsageTime;
+ private long mStartedTime;
+
+ public static final Parcelable.Creator<ConfigurationStats> CREATOR
+ = new Parcelable.Creator<ConfigurationStats>() {
+ public ConfigurationStats createFromParcel(Parcel in) {
+ return new ConfigurationStats(in);
+ }
+
+ public ConfigurationStats[] newArray(int size) {
+ return new ConfigurationStats[size];
+ }
+ };
+
+ public String toString() {
+ return "ConfigurationStats{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " " + mConfiguration + "}";
+ }
+
+ /** @hide */
+ public ConfigurationStats(Configuration config) {
+ mConfiguration = config;
+ }
+
+ /** @hide */
+ public ConfigurationStats(Parcel source) {
+ mConfiguration = Configuration.CREATOR.createFromParcel(source);
+ mLastUsedTime = source.readLong();
+ mUsageCount = source.readInt();
+ mUsageTime = source.readLong();
+ }
+
+ /** @hide */
+ public ConfigurationStats(ConfigurationStats pStats) {
+ mConfiguration = pStats.mConfiguration;
+ mLastUsedTime = pStats.mLastUsedTime;
+ mUsageCount = pStats.mUsageCount;
+ mUsageTime = pStats.mUsageTime;
+ }
+
+ public final Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
+ public final long getLastUsedTime() {
+ return mLastUsedTime;
+ }
+
+ public final long getUsageTime(long elapsedRealtime) {
+ return mUsageTime + (mStartedTime > 0 ? (elapsedRealtime- mStartedTime) : 0);
+ }
+
+ public final int getUsageCount() {
+ return mUsageCount;
+ }
+
+ /** @hide */
+ public void start() {
+ mLastUsedTime = System.currentTimeMillis();
+ mUsageCount++;
+ mStartedTime = SystemClock.elapsedRealtime();
+ }
+
+ /** @hide */
+ public void stop() {
+ if (mStartedTime > 0) {
+ mUsageTime += SystemClock.elapsedRealtime() - mStartedTime;
+ }
+ mStartedTime = 0;
+ }
+
+ /** @hide */
+ public boolean clearUsageTimes() {
+ mUsageCount = 0;
+ mUsageTime = 0;
+ return mLastUsedTime == 0 && mStartedTime <= 0;
+ }
+
+ public final int describeContents() {
+ return 0;
+ }
+
+ public final void writeToParcel(Parcel dest, int parcelableFlags) {
+ writeToParcel(dest, parcelableFlags, 0);
+ }
+
+ final void writeToParcel(Parcel dest, int parcelableFlags, long elapsedRealtime) {
+ mConfiguration.writeToParcel(dest, parcelableFlags);
+ dest.writeLong(mLastUsedTime);
+ dest.writeInt(mUsageCount);
+ dest.writeLong(elapsedRealtime > 0 ? getUsageTime(elapsedRealtime) : mUsageTime);
+ }
+
+ /** @hide */
+ public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+ }
+ }
+
+ /** @hide */
+ public UsageStats() {
+ }
+
+ /** @hide */
+ public UsageStats(Parcel source, boolean extended) {
+ int N = source.readInt();
+ for (int i=0; i<N; i++) {
+ PackageStats pkg = extended ? onNewPackageStats(source) : new PackageStats(source);
+ mPackages.put(pkg.getPackageName(), pkg);
+ }
+ N = source.readInt();
+ for (int i=0; i<N; i++) {
+ ConfigurationStats config = extended ? onNewConfigurationStats(source)
+ : new ConfigurationStats(source);
+ mConfigurations.put(config.getConfiguration(), config);
+ }
+ }
+
+ public int getPackageStatsCount() {
+ return mPackages.size();
+ }
+
+ public PackageStats getPackageStatsAt(int index) {
+ return mPackages.valueAt(index);
+ }
+
+ public PackageStats getPackageStats(String pkgName) {
+ return mPackages.get(pkgName);
+ }
+
+ /** @hide */
+ public PackageStats getOrCreatePackageStats(String pkgName) {
+ PackageStats ps = mPackages.get(pkgName);
+ if (ps == null) {
+ ps = onNewPackageStats(pkgName);
+ mPackages.put(pkgName, ps);
+ }
+ return ps;
+ }
+
+ public int getConfigurationStatsCount() {
+ return mConfigurations.size();
+ }
+
+ public ConfigurationStats getConfigurationStatsAt(int index) {
+ return mConfigurations.valueAt(index);
+ }
+
+ public ConfigurationStats getConfigurationStats(Configuration config) {
+ return mConfigurations.get(config);
+ }
+
+ /** @hide */
+ public ConfigurationStats getOrCreateConfigurationStats(Configuration config) {
+ ConfigurationStats cs = mConfigurations.get(config);
+ if (cs == null) {
+ cs = onNewConfigurationStats(config);
+ mConfigurations.put(config, cs);
+ }
+ return cs;
+ }
+
+ /** @hide */
+ public void clearUsageTimes() {
+ for (int i=mPackages.size()-1; i>=0; i--) {
+ if (mPackages.valueAt(i).clearUsageTimes()) {
+ mPackages.removeAt(i);
+ }
+ }
+ for (int i=mConfigurations.size()-1; i>=0; i--) {
+ if (mConfigurations.valueAt(i).clearUsageTimes()) {
+ mConfigurations.removeAt(i);
+ }
+ }
+ }
+
+ /** @hide */
+ public PackageStats onNewPackageStats(String pkgName) {
+ return new PackageStats(pkgName);
+ }
+
+ /** @hide */
+ public PackageStats onNewPackageStats(Parcel source) {
+ return new PackageStats(source);
+ }
+
+ /** @hide */
+ public ConfigurationStats onNewConfigurationStats(Configuration config) {
+ return new ConfigurationStats(config);
+ }
+
+ /** @hide */
+ public ConfigurationStats onNewConfigurationStats(Parcel source) {
+ return new ConfigurationStats(source);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int parcelableFlags) {
+ writeToParcelInner(dest, parcelableFlags, false);
+ }
+
+ /** @hide */
+ public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+ writeToParcelInner(dest, parcelableFlags, true);
+ }
+
+ private void writeToParcelInner(Parcel dest, int parcelableFlags, boolean extended) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+
+ int N = mPackages.size();
+ dest.writeInt(N);
+ for (int i=0; i<N; i++) {
+ PackageStats ps = mPackages.valueAt(i);
+ ps.writeToParcel(dest, parcelableFlags, elapsedRealtime);
+ if (extended) {
+ ps.writeExtendedToParcel(dest, parcelableFlags);
+ }
+ }
+ N = mConfigurations.size();
+ dest.writeInt(N);
+ for (int i=0; i<N; i++) {
+ ConfigurationStats cs = mConfigurations.valueAt(i);
+ cs.writeToParcel(dest, parcelableFlags, elapsedRealtime);
+ if (extended) {
+ cs.writeExtendedToParcel(dest, parcelableFlags);
+ }
+ }
+ }
+
+ public static final Parcelable.Creator<UsageStats> CREATOR
+ = new Parcelable.Creator<UsageStats>() {
+ public UsageStats createFromParcel(Parcel in) {
+ return new UsageStats(in, false);
+ }
+
+ public UsageStats[] newArray(int size) {
+ return new UsageStats[size];
+ }
+ };
+}
diff --git a/core/java/android/app/UsageStatsManager.java b/core/java/android/app/UsageStatsManager.java
new file mode 100644
index 0000000..fbf9c3b
--- /dev/null
+++ b/core/java/android/app/UsageStatsManager.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.os.ParcelableParcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import com.android.internal.app.IUsageStats;
+
+/**
+ * Access to usage stats data.
+ * @hide
+ */
+public class UsageStatsManager {
+ final Context mContext;
+ final IUsageStats mService;
+
+ /** @hide */
+ public UsageStatsManager(Context context) {
+ mContext = context;
+ mService = IUsageStats.Stub.asInterface(ServiceManager.getService(
+ Context.USAGE_STATS_SERVICE));
+ }
+
+ public UsageStats getCurrentStats() {
+ try {
+ ParcelableParcel in = mService.getCurrentStats(mContext.getOpPackageName());
+ if (in != null) {
+ return new UsageStats(in.getParcel(), false);
+ }
+ } catch (RemoteException e) {
+ // About to die.
+ }
+ return new UsageStats();
+ }
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 042ee28..a059e48 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2683,6 +2683,16 @@ public abstract class Context {
public static final String NETWORK_SCORE_SERVICE = "network_score";
/**
+ * Use with {@link #getSystemService} to retrieve a {@link
+ * android.app.UsageStatsManager} for interacting with the status bar.
+ *
+ * @see #getSystemService
+ * @see android.app.UsageStatsManager
+ * @hide
+ */
+ public static final String USAGE_STATS_SERVICE = "usagestats";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/os/ParcelableParcel.aidl b/core/java/android/os/ParcelableParcel.aidl
new file mode 100644
index 0000000..61f730c
--- /dev/null
+++ b/core/java/android/os/ParcelableParcel.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2014, 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.
+*/
+
+package android.os;
+
+parcelable ParcelableParcel;