Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17d3b47e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "UsageEvents for slices pinning" into pi-dev

parents 65808f32 1918ef75
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
  }

+14 −0
Original line number Diff line number Diff line
@@ -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;

+48 −25
Original line number Diff line number Diff line
@@ -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,6 +368,15 @@ 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).
                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();
@@ -362,9 +387,10 @@ public class SliceManagerService extends ISliceManager.Stub {
                try {
                    holder = activityManager.getContentProviderExternal(
                            providerName, getUserIdFromUri(uri, user), token);
                            if (holder == null || holder.info == null
                                    || !Objects.equals(holder.info.packageName, pkg)) {
                                return PERMISSION_DENIED;
                    if (holder != null && holder.info != null) {
                        return holder.info.packageName;
                    } else {
                        return null;
                    }
                } finally {
                    if (holder != null && holder.provider != null) {
@@ -373,16 +399,13 @@ public class SliceManagerService extends ISliceManager.Stub {
                }
            } catch (RemoteException e) {
                // Can't happen.
                        e.rethrowAsRuntimeException();
                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) {
        int user = Binder.getCallingUserHandle().getIdentifier();
+26 −0
Original line number Diff line number Diff line
@@ -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;
@@ -405,6 +407,30 @@ public class AppStandbyControllerTests {
        assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));
    }

    @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);
+4 −0
Original line number Diff line number Diff line
@@ -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
Loading