summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2018-03-21 16:07:32 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-03-21 16:07:32 +0000
commit17d3b47e2036f589f29b7436bcbcd27eb0ad1a3e (patch)
tree848b2bdd7d7b9b10f58daf2255a1ecd8cf021d2c
parent65808f321055d1d1a73812002ef440e3724e8d20 (diff)
parent1918ef7569e90c70246e535478b26732b82d92d3 (diff)
Merge "UsageEvents for slices pinning" into pi-dev
-rw-r--r--api/system-current.txt2
-rw-r--r--core/java/android/app/usage/UsageEvents.java14
-rw-r--r--services/core/java/com/android/server/slice/SliceManagerService.java73
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java26
-rw-r--r--services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java4
-rw-r--r--services/usage/java/com/android/server/usage/AppStandbyController.java11
-rw-r--r--services/usage/java/com/android/server/usage/UserUsageStatsService.java4
7 files changed, 105 insertions, 29 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index a5be12fdfc9c..1e2fe3df0d2c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -725,6 +725,8 @@ package android.app.usage {
method public java.lang.String getNotificationChannelId();
field public static final int NOTIFICATION_INTERRUPTION = 12; // 0xc
field public static final int NOTIFICATION_SEEN = 10; // 0xa
+ field public static final int SLICE_PINNED = 14; // 0xe
+ field public static final int SLICE_PINNED_PRIV = 13; // 0xd
field public static final int SYSTEM_INTERACTION = 6; // 0x6
}
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 8550ac0f32cd..b354e8122a98 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -125,6 +125,20 @@ public final class UsageEvents implements Parcelable {
@SystemApi
public static final int NOTIFICATION_INTERRUPTION = 12;
+ /**
+ * A Slice was pinned by the default launcher or the default assistant.
+ * @hide
+ */
+ @SystemApi
+ public static final int SLICE_PINNED_PRIV = 13;
+
+ /**
+ * A Slice was pinned by an app.
+ * @hide
+ */
+ @SystemApi
+ public static final int SLICE_PINNED = 14;
+
/** @hide */
public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index a7dfd35acf1b..0b7d9d02f1cb 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.slice;
+import static android.app.usage.UsageEvents.Event.SLICE_PINNED;
+import static android.app.usage.UsageEvents.Event.SLICE_PINNED_PRIV;
import static android.content.ContentProvider.getUriWithoutUserId;
import static android.content.ContentProvider.getUserIdFromUri;
import static android.content.ContentProvider.maybeAddUserId;
@@ -31,6 +33,7 @@ import android.app.IActivityManager;
import android.app.slice.ISliceManager;
import android.app.slice.SliceManager;
import android.app.slice.SliceSpec;
+import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -95,6 +98,7 @@ public class SliceManagerService extends ISliceManager.Stub {
private final AtomicFile mSliceAccessFile;
@GuardedBy("mAccessList")
private final SliceFullAccessList mAccessList;
+ private final UsageStatsManagerInternal mAppUsageStats;
public SliceManagerService(Context context) {
this(context, createHandler().getLooper());
@@ -112,6 +116,7 @@ public class SliceManagerService extends ISliceManager.Stub {
final File systemDir = new File(Environment.getDataDirectory(), "system");
mSliceAccessFile = new AtomicFile(new File(systemDir, "slice_access.xml"));
mAccessList = new SliceFullAccessList(mContext);
+ mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
synchronized (mSliceAccessFile) {
if (!mSliceAccessFile.exists()) return;
@@ -166,8 +171,19 @@ public class SliceManagerService extends ISliceManager.Stub {
public void pinSlice(String pkg, Uri uri, SliceSpec[] specs, IBinder token) throws RemoteException {
verifyCaller(pkg);
enforceAccess(pkg, uri);
- uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier());
+ int user = Binder.getCallingUserHandle().getIdentifier();
+ uri = maybeAddUserId(uri, user);
getOrCreatePinnedSlice(uri, pkg).pin(pkg, specs, token);
+
+ Uri finalUri = uri;
+ mHandler.post(() -> {
+ String slicePkg = getProviderPkg(finalUri, user);
+ if (slicePkg != null && !Objects.equals(pkg, slicePkg)) {
+ mAppUsageStats.reportEvent(slicePkg, user,
+ isAssistant(pkg, user) || isDefaultHomeApp(pkg, user)
+ ? SLICE_PINNED_PRIV : SLICE_PINNED);
+ }
+ });
}
@Override
@@ -352,36 +368,43 @@ public class SliceManagerService extends ISliceManager.Stub {
if (getContext().checkUriPermission(uri, pid, uid,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != PERMISSION_GRANTED) {
// Last fallback (if the calling app owns the authority, then it can have access).
- long ident = Binder.clearCallingIdentity();
+ if (!Objects.equals(getProviderPkg(uri, user), pkg)) {
+ return PERMISSION_DENIED;
+ }
+ }
+ }
+ return PERMISSION_GRANTED;
+ }
+
+ private String getProviderPkg(Uri uri, int user) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ IBinder token = new Binder();
+ IActivityManager activityManager = ActivityManager.getService();
+ ContentProviderHolder holder = null;
+ String providerName = getUriWithoutUserId(uri).getAuthority();
+ try {
try {
- IBinder token = new Binder();
- IActivityManager activityManager = ActivityManager.getService();
- ContentProviderHolder holder = null;
- String providerName = getUriWithoutUserId(uri).getAuthority();
- try {
- try {
- holder = activityManager.getContentProviderExternal(
- providerName, getUserIdFromUri(uri, user), token);
- if (holder == null || holder.info == null
- || !Objects.equals(holder.info.packageName, pkg)) {
- return PERMISSION_DENIED;
- }
- } finally {
- if (holder != null && holder.provider != null) {
- activityManager.removeContentProviderExternal(providerName, token);
- }
- }
- } catch (RemoteException e) {
- // Can't happen.
- e.rethrowAsRuntimeException();
+ holder = activityManager.getContentProviderExternal(
+ providerName, getUserIdFromUri(uri, user), token);
+ if (holder != null && holder.info != null) {
+ return holder.info.packageName;
+ } else {
+ return null;
}
} finally {
- // I know, the double finally seems ugly, but seems safest for the identity.
- Binder.restoreCallingIdentity(ident);
+ if (holder != null && holder.provider != null) {
+ activityManager.removeContentProviderExternal(providerName, token);
+ }
}
+ } catch (RemoteException e) {
+ // Can't happen.
+ throw e.rethrowAsRuntimeException();
}
+ } finally {
+ // I know, the double finally seems ugly, but seems safest for the identity.
+ Binder.restoreCallingIdentity(ident);
}
- return PERMISSION_GRANTED;
}
private void enforceCrossUser(String pkg, Uri uri) {
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index edf1f746fb4b..552c915f8480 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -17,6 +17,8 @@
package com.android.server.usage;
import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN;
+import static android.app.usage.UsageEvents.Event.SLICE_PINNED;
+import static android.app.usage.UsageEvents.Event.SLICE_PINNED_PRIV;
import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED;
@@ -406,6 +408,30 @@ public class AppStandbyControllerTests {
}
@Test
+ public void testSlicePinnedEvent() throws Exception {
+ setChargingState(mController, false);
+
+ reportEvent(mController, USER_INTERACTION, 0);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ mInjector.mElapsedRealtime = 1;
+ reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+
+ mController.forceIdleState(PACKAGE_1, USER_ID, true);
+ reportEvent(mController, SLICE_PINNED, mInjector.mElapsedRealtime);
+ assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));
+ }
+
+ @Test
+ public void testSlicePinnedPrivEvent() throws Exception {
+ setChargingState(mController, false);
+
+ mController.forceIdleState(PACKAGE_1, USER_ID, true);
+ reportEvent(mController, SLICE_PINNED_PRIV, mInjector.mElapsedRealtime);
+ assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
+ }
+
+ @Test
public void testPredictionTimedout() throws Exception {
setChargingState(mController, false);
// Set it to timeout or usage, so that prediction can override it
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index 4f446a9afb98..1073a800527a 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.app.slice.SliceSpec;
+import android.app.usage.UsageStatsManagerInternal;
import android.content.pm.PackageManagerInternal;
import android.net.Uri;
import android.os.Binder;
@@ -66,6 +67,8 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
@Before
public void setup() {
LocalServices.addService(PackageManagerInternal.class, mock(PackageManagerInternal.class));
+ LocalServices.addService(UsageStatsManagerInternal.class,
+ mock(UsageStatsManagerInternal.class));
mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
mContext.getTestablePermissions().setPermission(TEST_URI, PERMISSION_GRANTED);
@@ -77,6 +80,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
@After
public void teardown() {
LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
}
@Test
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index e836677e38fc..1af5f469c0f0 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -36,6 +36,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
@@ -43,8 +44,8 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.usage.AppStandbyInfo;
-import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
@@ -100,7 +101,6 @@ import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -690,7 +690,9 @@ public class AppStandbyController {
|| event.mEventType == UsageEvents.Event.MOVE_TO_BACKGROUND
|| event.mEventType == UsageEvents.Event.SYSTEM_INTERACTION
|| event.mEventType == UsageEvents.Event.USER_INTERACTION
- || event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN)) {
+ || event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN
+ || event.mEventType == UsageEvents.Event.SLICE_PINNED
+ || event.mEventType == UsageEvents.Event.SLICE_PINNED_PRIV)) {
final AppUsageHistory appHistory = mAppIdleHistory.getAppUsageHistory(
event.mPackage, userId, elapsedRealtime);
@@ -699,7 +701,8 @@ public class AppStandbyController {
final long nextCheckTime;
final int subReason = usageEventToSubReason(event.mEventType);
final int reason = REASON_MAIN_USAGE | subReason;
- if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN) {
+ if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN
+ || event.mEventType == UsageEvents.Event.SLICE_PINNED) {
// Mild usage elevates to WORKING_SET but doesn't change usage time.
mAppIdleHistory.reportUsage(appHistory, event.mPackage,
STANDBY_BUCKET_WORKING_SET, subReason,
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index d9742825ac70..c2e38f2f0bd8 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -761,6 +761,10 @@ class UserUsageStatsService {
return "STANDBY_BUCKET_CHANGED";
case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
return "NOTIFICATION_INTERRUPTION";
+ case UsageEvents.Event.SLICE_PINNED:
+ return "SLICE_PINNED";
+ case UsageEvents.Event.SLICE_PINNED_PRIV:
+ return "SLICE_PINNED_PRIV";
default:
return "UNKNOWN";
}