diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl index 38d9025cc82f8..20ec75a36ad3e 100644 --- a/core/java/android/app/slice/ISliceManager.aidl +++ b/core/java/android/app/slice/ISliceManager.aidl @@ -16,17 +16,13 @@ package android.app.slice; -import android.app.slice.ISliceListener; import android.app.slice.SliceSpec; import android.net.Uri; /** @hide */ interface ISliceManager { - void addSliceListener(in Uri uri, String pkg, in ISliceListener listener, - in SliceSpec[] specs); - void removeSliceListener(in Uri uri, String pkg, in ISliceListener listener); - void pinSlice(String pkg, in Uri uri, in SliceSpec[] specs); - void unpinSlice(String pkg, in Uri uri); + void pinSlice(String pkg, in Uri uri, in SliceSpec[] specs, in IBinder token); + void unpinSlice(String pkg, in Uri uri, in IBinder token); boolean hasSliceAccess(String pkg); SliceSpec[] getPinnedSpecs(in Uri uri, String pkg); int checkSlicePermission(in Uri uri, String pkg, int pid, int uid); diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index a978e5b54c45b..e2c866220c1e8 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -26,8 +26,10 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; @@ -73,6 +75,7 @@ public class SliceManager { private final Context mContext; private final ArrayMap, ISliceListener> mListenerLookup = new ArrayMap<>(); + private final IBinder mToken = new Binder(); /** * Permission denied. @@ -105,7 +108,6 @@ public class SliceManager { @Deprecated public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback, @NonNull List specs) { - registerSliceCallback(uri, specs, mContext.getMainExecutor(), callback); } /** @@ -114,7 +116,6 @@ public class SliceManager { @Deprecated public void registerSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback, @NonNull List specs, Executor executor) { - registerSliceCallback(uri, specs, executor, callback); } /** @@ -132,7 +133,6 @@ public class SliceManager { */ public void registerSliceCallback(@NonNull Uri uri, @NonNull List specs, @NonNull SliceCallback callback) { - registerSliceCallback(uri, specs, mContext.getMainExecutor(), callback); } /** @@ -150,32 +150,7 @@ public class SliceManager { */ public void registerSliceCallback(@NonNull Uri uri, @NonNull List specs, @NonNull @CallbackExecutor Executor executor, @NonNull SliceCallback callback) { - try { - mService.addSliceListener(uri, mContext.getPackageName(), - getListener(uri, callback, new ISliceListener.Stub() { - @Override - public void onSliceUpdated(Slice s) throws RemoteException { - executor.execute(() -> callback.onSliceUpdated(s)); - } - }), specs.toArray(new SliceSpec[specs.size()])); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - private ISliceListener getListener(Uri uri, SliceCallback callback, - ISliceListener listener) { - Pair key = new Pair<>(uri, callback); - if (mListenerLookup.containsKey(key)) { - try { - mService.removeSliceListener(uri, mContext.getPackageName(), - mListenerLookup.get(key)); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - mListenerLookup.put(key, listener); - return listener; } /** @@ -189,12 +164,7 @@ public class SliceManager { * @see #registerSliceCallback */ public void unregisterSliceCallback(@NonNull Uri uri, @NonNull SliceCallback callback) { - try { - mService.removeSliceListener(uri, mContext.getPackageName(), - mListenerLookup.remove(new Pair<>(uri, callback))); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + } /** @@ -215,7 +185,7 @@ public class SliceManager { public void pinSlice(@NonNull Uri uri, @NonNull List specs) { try { mService.pinSlice(mContext.getPackageName(), uri, - specs.toArray(new SliceSpec[specs.size()])); + specs.toArray(new SliceSpec[specs.size()]), mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -237,7 +207,7 @@ public class SliceManager { */ public void unpinSlice(@NonNull Uri uri) { try { - mService.unpinSlice(mContext.getPackageName(), uri); + mService.unpinSlice(mContext.getPackageName(), uri, mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java index 5d1bdabeeac83..deb975b783a13 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java @@ -160,8 +160,8 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe mRow.addView(button); PendingIntent pendingIntent = null; - if (rc.getContentIntent() != null) { - pendingIntent = rc.getContentIntent().getAction(); + if (rc.getPrimaryAction() != null) { + pendingIntent = rc.getPrimaryAction().getAction(); } mClickActions.put(button, pendingIntent); diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java index 8da16d7ea1488..f9a4ea211f073 100644 --- a/services/core/java/com/android/server/slice/PinnedSliceState.java +++ b/services/core/java/com/android/server/slice/PinnedSliceState.java @@ -16,7 +16,6 @@ package com.android.server.slice; import static android.app.slice.SliceManager.PERMISSION_GRANTED; -import android.app.slice.ISliceListener; import android.app.slice.Slice; import android.app.slice.SliceProvider; import android.app.slice.SliceSpec; @@ -106,10 +105,6 @@ public class PinnedSliceState { setSlicePinned(false); } - public void onChange() { - mService.getHandler().post(this::handleBind); - } - private void setSlicePinned(boolean pinned) { synchronized (mLock) { if (mSlicePinned == pinned) return; @@ -122,45 +117,23 @@ public class PinnedSliceState { } } - public void addSliceListener(ISliceListener listener, String pkg, SliceSpec[] specs, - boolean hasPermission) { + public void pin(String pkg, SliceSpec[] specs, IBinder token) { synchronized (mLock) { - if (mListeners.size() == 0) { - mService.listen(mUri); - } + mListeners.put(token, new ListenerInfo(token, pkg, true, + Binder.getCallingUid(), Binder.getCallingPid())); try { - listener.asBinder().linkToDeath(mDeathRecipient, 0); + token.linkToDeath(mDeathRecipient, 0); } catch (RemoteException e) { } - mListeners.put(listener.asBinder(), new ListenerInfo(listener, pkg, hasPermission, - Binder.getCallingUid(), Binder.getCallingPid())); mergeSpecs(specs); - setSlicePinned(hasPermission); - } - } - - public boolean removeSliceListener(ISliceListener listener) { - synchronized (mLock) { - listener.asBinder().unlinkToDeath(mDeathRecipient, 0); - if (mListeners.containsKey(listener.asBinder()) && mListeners.size() == 1) { - mService.unlisten(mUri); - } - mListeners.remove(listener.asBinder()); - } - return !hasPinOrListener(); - } - - public void pin(String pkg, SliceSpec[] specs) { - synchronized (mLock) { setSlicePinned(true); - mPinnedPkgs.add(pkg); - mergeSpecs(specs); } } - public boolean unpin(String pkg) { + public boolean unpin(String pkg, IBinder token) { synchronized (mLock) { - mPinnedPkgs.remove(pkg); + token.unlinkToDeath(mDeathRecipient, 0); + mListeners.remove(token); } return !hasPinOrListener(); } @@ -171,30 +144,6 @@ public class PinnedSliceState { } } - public void recheckPackage(String pkg) { - synchronized (mLock) { - for (int i = 0; i < mListeners.size(); i++) { - ListenerInfo info = mListeners.valueAt(i); - if (!info.hasPermission && Objects.equals(info.pkg, pkg)) { - mService.getHandler().post(() -> { - // This bind lets the app itself participate in the permission grant. - Slice s = doBind(info); - if (mService.checkAccess(info.pkg, mUri, info.callingUid, info.callingPid) - == PERMISSION_GRANTED) { - info.hasPermission = true; - setSlicePinned(true); - try { - info.listener.onSliceUpdated(s); - } catch (RemoteException e) { - checkSelfRemove(); - } - } - }); - } - } - } - } - @VisibleForTesting public boolean hasPinOrListener() { synchronized (mLock) { @@ -213,7 +162,6 @@ public class PinnedSliceState { private void checkSelfRemove() { if (!hasPinOrListener()) { // All the listeners died, remove from pinned state. - mService.unlisten(mUri); mService.removePinnedSlice(mUri); } } @@ -223,7 +171,7 @@ public class PinnedSliceState { synchronized (mLock) { for (int i = mListeners.size() - 1; i >= 0; i--) { ListenerInfo l = mListeners.valueAt(i); - if (!l.listener.asBinder().isBinderAlive()) { + if (!l.token.isBinderAlive()) { mListeners.removeAt(i); } } @@ -231,62 +179,6 @@ public class PinnedSliceState { } } - private void handleBind() { - Slice cachedSlice = doBind(null); - synchronized (mLock) { - if (!hasPinOrListener()) return; - for (int i = mListeners.size() - 1; i >= 0; i--) { - ListenerInfo info = mListeners.valueAt(i); - Slice s = cachedSlice; - if (s == null || s.hasHint(Slice.HINT_CALLER_NEEDED) - || !info.hasPermission) { - s = doBind(info); - } - if (s == null) { - mListeners.removeAt(i); - continue; - } - try { - info.listener.onSliceUpdated(s); - } catch (RemoteException e) { - Log.e(TAG, "Unable to notify slice " + mUri, e); - mListeners.removeAt(i); - continue; - } - } - checkSelfRemove(); - } - } - - private Slice doBind(ListenerInfo info) { - try (ContentProviderClient client = getClient()) { - if (client == null) return null; - Bundle extras = new Bundle(); - extras.putParcelable(SliceProvider.EXTRA_BIND_URI, mUri); - extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, - new ArrayList<>(Arrays.asList(mSupportedSpecs))); - if (info != null) { - extras.putString(SliceProvider.EXTRA_OVERRIDE_PKG, info.pkg); - extras.putInt(SliceProvider.EXTRA_OVERRIDE_UID, info.callingUid); - extras.putInt(SliceProvider.EXTRA_OVERRIDE_PID, info.callingPid); - } - final Bundle res; - try { - res = client.call(SliceProvider.METHOD_SLICE, null, extras); - } catch (RemoteException e) { - Log.e(TAG, "Unable to bind slice " + mUri, e); - return null; - } - if (res == null) return null; - Bundle.setDefusable(res, true); - return res.getParcelable(SliceProvider.EXTRA_SLICE); - } catch (Throwable t) { - // Calling out of the system process, make sure they don't throw anything at us. - Log.e(TAG, "Caught throwable while binding " + mUri, t); - return null; - } - } - private void handleSendPinned() { try (ContentProviderClient client = getClient()) { if (client == null) return; @@ -315,15 +207,15 @@ public class PinnedSliceState { private class ListenerInfo { - private ISliceListener listener; + private IBinder token; private String pkg; private boolean hasPermission; private int callingUid; private int callingPid; - public ListenerInfo(ISliceListener listener, String pkg, boolean hasPermission, + public ListenerInfo(IBinder token, String pkg, boolean hasPermission, int callingUid, int callingPid) { - this.listener = listener; + this.token = token; this.pkg = pkg; this.hasPermission = hasPermission; this.callingUid = callingUid; diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java index a1def440a0079..51e4709aa7c73 100644 --- a/services/core/java/com/android/server/slice/SliceManagerService.java +++ b/services/core/java/com/android/server/slice/SliceManagerService.java @@ -28,7 +28,6 @@ import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.ContentProviderHolder; import android.app.IActivityManager; -import android.app.slice.ISliceListener; import android.app.slice.ISliceManager; import android.app.slice.SliceManager; import android.app.slice.SliceSpec; @@ -39,7 +38,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; -import android.database.ContentObserver; import android.net.Uri; import android.os.Binder; import android.os.Environment; @@ -52,7 +50,6 @@ import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; -import android.util.Log; import android.util.Slog; import android.util.Xml.Encoding; @@ -94,7 +91,6 @@ public class SliceManagerService extends ISliceManager.Stub { @GuardedBy("mLock") private final ArraySet mUserGrants = new ArraySet<>(); private final Handler mHandler; - private final ContentObserver mObserver; @GuardedBy("mSliceAccessFile") private final AtomicFile mSliceAccessFile; @GuardedBy("mAccessList") @@ -113,16 +109,6 @@ public class SliceManagerService extends ISliceManager.Stub { mAssistUtils = new AssistUtils(context); mHandler = new Handler(looper); - mObserver = new ContentObserver(mHandler) { - @Override - public void onChange(boolean selfChange, Uri uri, int userId) { - try { - getPinnedSlice(maybeAddUserId(uri, userId)).onChange(); - } catch (IllegalStateException e) { - Log.e(TAG, "Received change for unpinned slice " + uri, e); - } - } - }; final File systemDir = new File(Environment.getDataDirectory(), "system"); mSliceAccessFile = new AtomicFile(new File(systemDir, "slice_access.xml")); mAccessList = new SliceFullAccessList(mContext); @@ -163,40 +149,19 @@ public class SliceManagerService extends ISliceManager.Stub { /// ----- ISliceManager stuff ----- @Override - public void addSliceListener(Uri uri, String pkg, ISliceListener listener, SliceSpec[] specs) - throws RemoteException { + public void pinSlice(String pkg, Uri uri, SliceSpec[] specs, IBinder token) throws RemoteException { verifyCaller(pkg); + enforceAccess(pkg, uri); uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier()); - enforceCrossUser(pkg, uri); - getOrCreatePinnedSlice(uri).addSliceListener(listener, pkg, specs, - checkAccess(pkg, uri, Binder.getCallingUid(), Binder.getCallingUid()) - == PERMISSION_GRANTED); + getOrCreatePinnedSlice(uri).pin(pkg, specs, token); } @Override - public void removeSliceListener(Uri uri, String pkg, ISliceListener listener) - throws RemoteException { + public void unpinSlice(String pkg, Uri uri, IBinder token) throws RemoteException { verifyCaller(pkg); + enforceAccess(pkg, uri); uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier()); - if (getPinnedSlice(uri).removeSliceListener(listener)) { - removePinnedSlice(uri); - } - } - - @Override - public void pinSlice(String pkg, Uri uri, SliceSpec[] specs) throws RemoteException { - verifyCaller(pkg); - enforceFullAccess(pkg, "pinSlice", uri); - uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier()); - getOrCreatePinnedSlice(uri).pin(pkg, specs); - } - - @Override - public void unpinSlice(String pkg, Uri uri) throws RemoteException { - verifyCaller(pkg); - enforceFullAccess(pkg, "unpinSlice", uri); - uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier()); - if (getPinnedSlice(uri).unpin(pkg)) { + if (getPinnedSlice(uri).unpin(pkg, token)) { removePinnedSlice(uri); } } @@ -253,11 +218,6 @@ public class SliceManagerService extends ISliceManager.Stub { } finally { Binder.restoreCallingIdentity(ident); } - synchronized (mLock) { - for (PinnedSliceState p : mPinnedSlicesByUri.values()) { - p.recheckPackage(pkg); - } - } } // Backup/restore interface @@ -457,21 +417,6 @@ public class SliceManagerService extends ISliceManager.Stub { return cn.getPackageName().equals(pkg); } - public void listen(Uri uri) { - mContext.getContentResolver().registerContentObserver(uri, true, mObserver); - } - - public void unlisten(Uri uri) { - mContext.getContentResolver().unregisterContentObserver(mObserver); - synchronized (mLock) { - mPinnedSlicesByUri.forEach((u, s) -> { - if (s.isListening()) { - listen(u); - } - }); - } - } - private boolean isDefaultHomeApp(String pkg, int userId) { String defaultHome = getDefaultHome(userId); 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 cfd155e81a67b..1052e8f377a79 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java @@ -71,6 +71,7 @@ public class PinnedSliceStateTest extends UiServiceTestCase { private PinnedSliceState mPinnedSliceManager; private IContentProvider mIContentProvider; private ContentProvider mContentProvider; + private IBinder mToken = new Binder(); @Before public void setup() { @@ -108,7 +109,7 @@ public class PinnedSliceStateTest extends UiServiceTestCase { TestableLooper.get(this).processAllMessages(); // When pinned for the first time, a pinned message should be sent. - mPinnedSliceManager.pin("pkg", FIRST_SPECS); + mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken); TestableLooper.get(this).processAllMessages(); verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null), @@ -118,113 +119,28 @@ public class PinnedSliceStateTest extends UiServiceTestCase { })); } - @Test - public void testSendPinnedOnListen() throws RemoteException { - TestableLooper.get(this).processAllMessages(); - - // When a listener is added for the first time, a pinned message should be sent. - ISliceListener listener = mock(ISliceListener.class); - when(listener.asBinder()).thenReturn(new Binder()); - - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS, - true); - TestableLooper.get(this).processAllMessages(); - - verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null), - argThat(b -> { - assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI)); - return true; - })); - } - - @Test - public void testNoSendPinnedWithoutPermission() throws RemoteException { - TestableLooper.get(this).processAllMessages(); - - // When a listener is added for the first time, a pinned message should be sent. - ISliceListener listener = mock(ISliceListener.class); - when(listener.asBinder()).thenReturn(new Binder()); - - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS, - false); - TestableLooper.get(this).processAllMessages(); - - verify(mIContentProvider, never()).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null), - any()); - } - - @Test - public void testSendUnpinnedOnDestroy() throws RemoteException { - TestableLooper.get(this).processAllMessages(); - clearInvocations(mIContentProvider); - - mPinnedSliceManager.pin("pkg", FIRST_SPECS); - mPinnedSliceManager.destroy(); - TestableLooper.get(this).processAllMessages(); - - verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_UNPIN), eq(null), - argThat(b -> { - assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI)); - return true; - })); - } - @Test public void testPkgPin() { assertFalse(mPinnedSliceManager.hasPinOrListener()); - mPinnedSliceManager.pin("pkg", FIRST_SPECS); + mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken); assertTrue(mPinnedSliceManager.hasPinOrListener()); - assertTrue(mPinnedSliceManager.unpin("pkg")); + assertTrue(mPinnedSliceManager.unpin("pkg", mToken)); assertFalse(mPinnedSliceManager.hasPinOrListener()); } @Test public void testMultiPkgPin() { + IBinder t2 = new Binder(); assertFalse(mPinnedSliceManager.hasPinOrListener()); - mPinnedSliceManager.pin("pkg", FIRST_SPECS); + mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken); assertTrue(mPinnedSliceManager.hasPinOrListener()); - mPinnedSliceManager.pin("pkg2", FIRST_SPECS); + mPinnedSliceManager.pin("pkg2", FIRST_SPECS, t2); - assertFalse(mPinnedSliceManager.unpin("pkg")); - assertTrue(mPinnedSliceManager.unpin("pkg2")); - assertFalse(mPinnedSliceManager.hasPinOrListener()); - } - - @Test - public void testListenerPin() { - ISliceListener listener = mock(ISliceListener.class); - when(listener.asBinder()).thenReturn(new Binder()); - assertFalse(mPinnedSliceManager.hasPinOrListener()); - - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS, - true); - assertTrue(mPinnedSliceManager.hasPinOrListener()); - - assertTrue(mPinnedSliceManager.removeSliceListener(listener)); - assertFalse(mPinnedSliceManager.hasPinOrListener()); - } - - @Test - public void testMultiListenerPin() { - ISliceListener listener = mock(ISliceListener.class); - Binder value = new Binder(); - when(listener.asBinder()).thenReturn(value); - ISliceListener listener2 = mock(ISliceListener.class); - Binder value2 = new Binder(); - when(listener2.asBinder()).thenReturn(value2); - assertFalse(mPinnedSliceManager.hasPinOrListener()); - - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS, - true); - assertTrue(mPinnedSliceManager.hasPinOrListener()); - mPinnedSliceManager.addSliceListener(listener2, mContext.getPackageName(), FIRST_SPECS, - true); - - assertFalse(mPinnedSliceManager.removeSliceListener(listener)); - assertTrue(mPinnedSliceManager.removeSliceListener(listener2)); + assertFalse(mPinnedSliceManager.unpin("pkg", mToken)); + assertTrue(mPinnedSliceManager.unpin("pkg2", t2)); assertFalse(mPinnedSliceManager.hasPinOrListener()); } @@ -236,8 +152,7 @@ public class PinnedSliceStateTest extends UiServiceTestCase { when(listener.asBinder()).thenReturn(binder); assertFalse(mPinnedSliceManager.hasPinOrListener()); - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS, - true); + mPinnedSliceManager.pin(mContext.getPackageName(), FIRST_SPECS, binder); assertTrue(mPinnedSliceManager.hasPinOrListener()); ArgumentCaptor arg = ArgumentCaptor.forClass(DeathRecipient.class); @@ -246,79 +161,7 @@ public class PinnedSliceStateTest extends UiServiceTestCase { when(binder.isBinderAlive()).thenReturn(false); arg.getValue().binderDied(); - verify(mSliceService).unlisten(eq(TEST_URI)); verify(mSliceService).removePinnedSlice(eq(TEST_URI)); assertFalse(mPinnedSliceManager.hasPinOrListener()); } - - @Test - public void testPkgListenerPin() { - ISliceListener listener = mock(ISliceListener.class); - when(listener.asBinder()).thenReturn(new Binder()); - assertFalse(mPinnedSliceManager.hasPinOrListener()); - - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS, - true); - assertTrue(mPinnedSliceManager.hasPinOrListener()); - mPinnedSliceManager.pin("pkg", FIRST_SPECS); - - assertFalse(mPinnedSliceManager.removeSliceListener(listener)); - assertTrue(mPinnedSliceManager.unpin("pkg")); - assertFalse(mPinnedSliceManager.hasPinOrListener()); - } - - @Test - public void testBind() throws RemoteException { - TestableLooper.get(this).processAllMessages(); - clearInvocations(mIContentProvider); - - ISliceListener listener = mock(ISliceListener.class); - when(listener.asBinder()).thenReturn(new Binder()); - Slice s = new Slice.Builder(TEST_URI).build(); - Bundle b = new Bundle(); - b.putParcelable(SliceProvider.EXTRA_SLICE, s); - when(mIContentProvider.call(anyString(), eq(SliceProvider.METHOD_SLICE), eq(null), - any())).thenReturn(b); - - assertFalse(mPinnedSliceManager.hasPinOrListener()); - - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS, - true); - - mPinnedSliceManager.onChange(); - TestableLooper.get(this).processAllMessages(); - - verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_SLICE), eq(null), - argThat(bundle -> { - assertEquals(TEST_URI, bundle.getParcelable(SliceProvider.EXTRA_BIND_URI)); - return true; - })); - verify(listener).onSliceUpdated(eq(s)); - } - - @Test - public void testRecheckPackage() throws RemoteException { - TestableLooper.get(this).processAllMessages(); - - ISliceListener listener = mock(ISliceListener.class); - when(listener.asBinder()).thenReturn(new Binder()); - - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS, - false); - TestableLooper.get(this).processAllMessages(); - - verify(mIContentProvider, never()).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null), - any()); - - when(mSliceService.checkAccess(any(), any(), anyInt(), anyInt())) - .thenReturn(PERMISSION_GRANTED); - mPinnedSliceManager.recheckPackage(mContext.getPackageName()); - TestableLooper.get(this).processAllMessages(); - - verify(mIContentProvider).call(anyString(), eq(SliceProvider.METHOD_PIN), eq(null), - argThat(b -> { - assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI)); - return true; - })); - } } \ 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 fe9ea7a1bb9b3..6fc300959144c 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java @@ -32,6 +32,8 @@ import android.app.slice.ISliceListener; import android.app.slice.SliceSpec; import android.content.pm.PackageManagerInternal; import android.net.Uri; +import android.os.Binder; +import android.os.IBinder; import android.os.RemoteException; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; @@ -59,6 +61,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase { private SliceManagerService mService; private PinnedSliceState mCreatedSliceState; + private IBinder mToken = new Binder(); @Before public void setup() { @@ -76,44 +79,12 @@ public class SliceManagerServiceTest extends UiServiceTestCase { LocalServices.removeServiceForTest(PackageManagerInternal.class); } - @Test - public void testAddListenerCreatesPinned() throws RemoteException { - mService.addSliceListener(TEST_URI, "pkg", mock(ISliceListener.class), EMPTY_SPECS); - verify(mService, times(1)).createPinnedSlice(eq(TEST_URI)); - } - - @Test - public void testAddListenerCreatesOnePinned() throws RemoteException { - mService.addSliceListener(TEST_URI, "pkg", mock(ISliceListener.class), EMPTY_SPECS); - mService.addSliceListener(TEST_URI, "pkg", mock(ISliceListener.class), EMPTY_SPECS); - verify(mService, times(1)).createPinnedSlice(eq(TEST_URI)); - } - - @Test - public void testRemoveListenerDestroysPinned() throws RemoteException { - ISliceListener listener = mock(ISliceListener.class); - mService.addSliceListener(TEST_URI, "pkg", listener, EMPTY_SPECS); - - when(mCreatedSliceState.removeSliceListener(eq(listener))).thenReturn(false); - mService.removeSliceListener(TEST_URI, "pkg", listener); - verify(mCreatedSliceState, never()).destroy(); - - when(mCreatedSliceState.removeSliceListener(eq(listener))).thenReturn(true); - mService.removeSliceListener(TEST_URI, "pkg", listener); - verify(mCreatedSliceState).destroy(); - } - - @Test(expected = IllegalStateException.class) - public void testUnrecognizedThrows() throws RemoteException { - mService.removeSliceListener(TEST_URI, "pkg", mock(ISliceListener.class)); - } - @Test public void testAddPinCreatesPinned() throws RemoteException { doReturn("pkg").when(mService).getDefaultHome(anyInt()); - mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS); - mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS); + mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); + mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); verify(mService, times(1)).createPinnedSlice(eq(TEST_URI)); } @@ -121,15 +92,11 @@ public class SliceManagerServiceTest extends UiServiceTestCase { public void testRemovePinDestroysPinned() throws RemoteException { doReturn("pkg").when(mService).getDefaultHome(anyInt()); - mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS); + mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); - when(mCreatedSliceState.unpin(eq("pkg"))).thenReturn(false); - mService.unpinSlice("pkg", TEST_URI); + when(mCreatedSliceState.unpin(eq("pkg"), eq(mToken))).thenReturn(false); + mService.unpinSlice("pkg", TEST_URI, mToken); verify(mCreatedSliceState, never()).destroy(); - - when(mCreatedSliceState.unpin(eq("pkg"))).thenReturn(true); - mService.unpinSlice("pkg", TEST_URI); - verify(mCreatedSliceState).destroy(); } } \ No newline at end of file