Merge "Add API to get currently pinned slices" into pi-dev
diff --git a/api/current.txt b/api/current.txt
index b3be727..f92896d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7266,6 +7266,7 @@
   public class SliceManager {
     method public android.app.slice.Slice bindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
     method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List<android.app.slice.SliceSpec>);
+    method public java.util.List<android.net.Uri> getPinnedSlices();
     method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri);
     method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri);
     method public android.net.Uri mapIntentToUri(android.content.Intent);
diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl
index 20ec75a..74e3c3e 100644
--- a/core/java/android/app/slice/ISliceManager.aidl
+++ b/core/java/android/app/slice/ISliceManager.aidl
@@ -27,6 +27,7 @@
     SliceSpec[] getPinnedSpecs(in Uri uri, String pkg);
     int checkSlicePermission(in Uri uri, String pkg, int pid, int uid);
     void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices);
+    Uri[] getPinnedSlices(String pkg);
 
     byte[] getBackupPayload(int user);
     void applyRestore(in byte[] payload, int user);
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 4f3cd63..c5ea9b2 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -184,6 +184,18 @@
     }
 
     /**
+     * Get the list of currently pinned slices for this app.
+     * @see SliceProvider#onSlicePinned
+     */
+    public @NonNull List<Uri> getPinnedSlices() {
+        try {
+            return Arrays.asList(mService.getPinnedSlices(mContext.getPackageName()));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Obtains a list of slices that are descendants of the specified Uri.
      * <p>
      * Not all slice providers will implement this functionality, in which case,
diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java
index f9a4ea2..4e7fb96 100644
--- a/services/core/java/com/android/server/slice/PinnedSliceState.java
+++ b/services/core/java/com/android/server/slice/PinnedSliceState.java
@@ -14,9 +14,6 @@
 
 package com.android.server.slice;
 
-import static android.app.slice.SliceManager.PERMISSION_GRANTED;
-
-import android.app.slice.Slice;
 import android.app.slice.SliceProvider;
 import android.app.slice.SliceSpec;
 import android.content.ContentProviderClient;
@@ -33,7 +30,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -54,18 +50,24 @@
     private final ArraySet<String> mPinnedPkgs = new ArraySet<>();
     @GuardedBy("mLock")
     private final ArrayMap<IBinder, ListenerInfo> mListeners = new ArrayMap<>();
+    private final String mPkg;
     @GuardedBy("mLock")
     private SliceSpec[] mSupportedSpecs = null;
 
     private final DeathRecipient mDeathRecipient = this::handleRecheckListeners;
     private boolean mSlicePinned;
 
-    public PinnedSliceState(SliceManagerService service, Uri uri) {
+    public PinnedSliceState(SliceManagerService service, Uri uri, String pkg) {
         mService = service;
         mUri = uri;
+        mPkg = pkg;
         mLock = mService.getLock();
     }
 
+    public String getPkg() {
+        return mPkg;
+    }
+
     public SliceSpec[] getSpecs() {
         return mSupportedSpecs;
     }
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 51e4709..a7dfd35 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -149,11 +149,25 @@
 
     ///  ----- ISliceManager stuff -----
     @Override
+    public Uri[] getPinnedSlices(String pkg) {
+        verifyCaller(pkg);
+        ArrayList<Uri> ret = new ArrayList<>();
+        synchronized (mLock) {
+            for (PinnedSliceState state : mPinnedSlicesByUri.values()) {
+                if (Objects.equals(pkg, state.getPkg())) {
+                    ret.add(state.getUri());
+                }
+            }
+        }
+        return ret.toArray(new Uri[ret.size()]);
+    }
+
+    @Override
     public void pinSlice(String pkg, Uri uri, SliceSpec[] specs, IBinder token) throws RemoteException {
         verifyCaller(pkg);
         enforceAccess(pkg, uri);
         uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier());
-        getOrCreatePinnedSlice(uri).pin(pkg, specs, token);
+        getOrCreatePinnedSlice(uri, pkg).pin(pkg, specs, token);
     }
 
     @Override
@@ -302,11 +316,11 @@
         }
     }
 
-    private PinnedSliceState getOrCreatePinnedSlice(Uri uri) {
+    private PinnedSliceState getOrCreatePinnedSlice(Uri uri, String pkg) {
         synchronized (mLock) {
             PinnedSliceState manager = mPinnedSlicesByUri.get(uri);
             if (manager == null) {
-                manager = createPinnedSlice(uri);
+                manager = createPinnedSlice(uri, pkg);
                 mPinnedSlicesByUri.put(uri, manager);
             }
             return manager;
@@ -314,8 +328,8 @@
     }
 
     @VisibleForTesting
-    protected PinnedSliceState createPinnedSlice(Uri uri) {
-        return new PinnedSliceState(this, uri);
+    protected PinnedSliceState createPinnedSlice(Uri uri, String pkg) {
+        return new PinnedSliceState(this, uri, pkg);
     }
 
     public Object getLock() {
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index 1052e8f..3c4e333 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -1,7 +1,5 @@
 package com.android.server.slice;
 
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -12,23 +10,18 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.slice.ISliceListener;
-import android.app.slice.Slice;
 import android.app.slice.SliceProvider;
 import android.app.slice.SliceSpec;
 import android.content.ContentProvider;
-import android.content.Context;
 import android.content.IContentProvider;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
@@ -83,7 +76,7 @@
         mIContentProvider = mock(IContentProvider.class);
         when(mContentProvider.getIContentProvider()).thenReturn(mIContentProvider);
         mContext.getContentResolver().addProvider(AUTH, mContentProvider);
-        mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI);
+        mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI, "pkg");
     }
 
     @Test
@@ -164,4 +157,4 @@
         verify(mSliceService).removePinnedSlice(eq(TEST_URI));
         assertFalse(mPinnedSliceManager.hasPinOrListener());
     }
-}
\ No newline at end of file
+}
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 6fc3009..4f446a9 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -18,6 +18,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -28,7 +29,6 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AppOpsManager;
-import android.app.slice.ISliceListener;
 import android.app.slice.SliceSpec;
 import android.content.pm.PackageManagerInternal;
 import android.net.Uri;
@@ -71,7 +71,7 @@
 
         mService = spy(new SliceManagerService(mContext, TestableLooper.get(this).getLooper()));
         mCreatedSliceState = mock(PinnedSliceState.class);
-        doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI));
+        doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI), anyString());
     }
 
     @After
@@ -85,7 +85,7 @@
 
         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
-        verify(mService, times(1)).createPinnedSlice(eq(TEST_URI));
+        verify(mService, times(1)).createPinnedSlice(eq(TEST_URI), eq("pkg"));
     }
 
     @Test