OSDN Git Service

Merge "docs: Add documentation for equals() method" into qt-dev am: 732a127636
[android-x86/frameworks-base.git] / services / tests / uiservicestests / src / com / android / server / slice / PinnedSliceStateTest.java
1 package com.android.server.slice;
2
3 import static android.testing.TestableContentResolver.UNSTABLE;
4
5 import static org.junit.Assert.assertArrayEquals;
6 import static org.junit.Assert.assertEquals;
7 import static org.junit.Assert.assertFalse;
8 import static org.junit.Assert.assertNull;
9 import static org.junit.Assert.assertTrue;
10 import static org.mockito.ArgumentMatchers.any;
11 import static org.mockito.ArgumentMatchers.anyInt;
12 import static org.mockito.ArgumentMatchers.anyString;
13 import static org.mockito.ArgumentMatchers.argThat;
14 import static org.mockito.ArgumentMatchers.eq;
15 import static org.mockito.Mockito.doAnswer;
16 import static org.mockito.Mockito.mock;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.when;
19
20 import android.app.slice.ISliceListener;
21 import android.app.slice.SliceProvider;
22 import android.app.slice.SliceSpec;
23 import android.content.ContentProvider;
24 import android.content.IContentProvider;
25 import android.net.Uri;
26 import android.os.Binder;
27 import android.os.Handler;
28 import android.os.IBinder;
29 import android.os.IBinder.DeathRecipient;
30 import android.os.RemoteException;
31 import android.testing.AndroidTestingRunner;
32 import android.testing.TestableLooper;
33 import android.testing.TestableLooper.RunWithLooper;
34
35 import androidx.test.filters.SmallTest;
36
37 import com.android.server.UiServiceTestCase;
38
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.mockito.ArgumentCaptor;
43
44 @SmallTest
45 @RunWith(AndroidTestingRunner.class)
46 @RunWithLooper
47 public class PinnedSliceStateTest extends UiServiceTestCase {
48
49     private static final String AUTH = "my.authority";
50     private static final Uri TEST_URI = Uri.parse("content://" + AUTH + "/path");
51
52     private static final SliceSpec[] FIRST_SPECS = new SliceSpec[]{
53             new SliceSpec("spec1", 3),
54             new SliceSpec("spec2", 3),
55             new SliceSpec("spec3", 2),
56             new SliceSpec("spec4", 1),
57     };
58
59     private static final SliceSpec[] SECOND_SPECS = new SliceSpec[]{
60             new SliceSpec("spec2", 1),
61             new SliceSpec("spec3", 2),
62             new SliceSpec("spec4", 3),
63             new SliceSpec("spec5", 4),
64     };
65
66     private SliceManagerService mSliceService;
67     private PinnedSliceState mPinnedSliceManager;
68     private IContentProvider mIContentProvider;
69     private ContentProvider mContentProvider;
70     private IBinder mToken = new Binder();
71
72     @Before
73     public void setUp() {
74         mSliceService = mock(SliceManagerService.class);
75         when(mSliceService.getContext()).thenReturn(mContext);
76         when(mSliceService.getLock()).thenReturn(new Object());
77         when(mSliceService.getHandler()).thenReturn(
78                 new Handler(TestableLooper.get(this).getLooper()));
79         mContentProvider = mock(ContentProvider.class);
80         mIContentProvider = mock(IContentProvider.class);
81         when(mContentProvider.getIContentProvider()).thenReturn(mIContentProvider);
82         mContext.getContentResolver().addProvider(AUTH, mContentProvider, UNSTABLE);
83         mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI, "pkg");
84     }
85
86     @Test
87     public void testMergeSpecs() {
88         // No annotations to start.
89         assertNull(mPinnedSliceManager.getSpecs());
90
91         mPinnedSliceManager.mergeSpecs(FIRST_SPECS);
92         assertArrayEquals(FIRST_SPECS, mPinnedSliceManager.getSpecs());
93
94         mPinnedSliceManager.mergeSpecs(SECOND_SPECS);
95         assertArrayEquals(new SliceSpec[]{
96                 // spec1 is gone because it's not in the second set.
97                 new SliceSpec("spec2", 1), // spec2 is 1 because it's smaller in the second set.
98                 new SliceSpec("spec3", 2), // spec3 is the same in both sets
99                 new SliceSpec("spec4", 1), // spec4 is 1 because it's smaller in the first set.
100                 // spec5 is gone because it's not in the first set.
101         }, mPinnedSliceManager.getSpecs());
102     }
103
104     @Test
105     public void testSendPinnedOnPin() throws RemoteException {
106         TestableLooper.get(this).processAllMessages();
107
108         // When pinned for the first time, a pinned message should be sent.
109         mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
110         TestableLooper.get(this).processAllMessages();
111
112         verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN),
113                 eq(null), argThat(b -> {
114                     assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
115                     return true;
116                 }));
117     }
118
119     @Test
120     public void testPkgPin() {
121         assertFalse(mPinnedSliceManager.hasPinOrListener());
122
123         mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
124         assertTrue(mPinnedSliceManager.hasPinOrListener());
125
126         assertTrue(mPinnedSliceManager.unpin("pkg", mToken));
127         assertFalse(mPinnedSliceManager.hasPinOrListener());
128     }
129
130     @Test
131     public void testMultiPkgPin() {
132         IBinder t2 = new Binder();
133         assertFalse(mPinnedSliceManager.hasPinOrListener());
134
135         mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
136         assertTrue(mPinnedSliceManager.hasPinOrListener());
137         mPinnedSliceManager.pin("pkg2", FIRST_SPECS, t2);
138
139         assertFalse(mPinnedSliceManager.unpin("pkg", mToken));
140         assertTrue(mPinnedSliceManager.unpin("pkg2", t2));
141         assertFalse(mPinnedSliceManager.hasPinOrListener());
142     }
143
144     @Test
145     public void testListenerDeath() throws RemoteException {
146         ISliceListener listener = mock(ISliceListener.class);
147         IBinder binder = mock(IBinder.class);
148         when(binder.isBinderAlive()).thenReturn(true);
149         when(listener.asBinder()).thenReturn(binder);
150         assertFalse(mPinnedSliceManager.hasPinOrListener());
151
152         mPinnedSliceManager.pin(mContext.getPackageName(), FIRST_SPECS, binder);
153         assertTrue(mPinnedSliceManager.hasPinOrListener());
154
155         ArgumentCaptor<DeathRecipient> arg = ArgumentCaptor.forClass(DeathRecipient.class);
156         verify(binder).linkToDeath(arg.capture(), anyInt());
157
158         when(binder.isBinderAlive()).thenReturn(false);
159         arg.getValue().binderDied();
160
161         verify(mSliceService).removePinnedSlice(eq(TEST_URI));
162         assertFalse(mPinnedSliceManager.hasPinOrListener());
163     }
164
165     @Test
166     public void testPinFailed() throws Exception {
167         // Throw exception when trying to pin
168         doAnswer(invocation -> {
169             throw new Exception("Pin failed");
170         }).when(mIContentProvider).call(
171                 anyString(), anyString(), anyString(), eq(null), any());
172
173         TestableLooper.get(this).processAllMessages();
174
175         // When pinned for the first time, a pinned message should be sent.
176         mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
177         TestableLooper.get(this).processAllMessages();
178
179         verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN),
180                 eq(null), argThat(b -> {
181                     assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
182                     return true;
183                 }));
184     }
185 }