1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.server.slice;
16 
17 import static android.content.ContentProvider.maybeAddUserId;
18 import static android.content.pm.PackageManager.PERMISSION_DENIED;
19 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.anyInt;
24 import static org.mockito.ArgumentMatchers.anyString;
25 import static org.mockito.ArgumentMatchers.eq;
26 import static org.mockito.Mockito.doReturn;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.never;
29 import static org.mockito.Mockito.spy;
30 import static org.mockito.Mockito.times;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33 
34 import android.app.AppOpsManager;
35 import android.app.slice.SliceSpec;
36 import android.app.usage.UsageStatsManagerInternal;
37 import android.net.Uri;
38 import android.os.Binder;
39 import android.os.IBinder;
40 import android.os.Process;
41 import android.os.RemoteException;
42 import android.testing.AndroidTestingRunner;
43 import android.testing.TestableContext;
44 import android.testing.TestableLooper;
45 import android.testing.TestableLooper.RunWithLooper;
46 
47 import androidx.test.filters.SmallTest;
48 
49 import com.android.server.LocalServices;
50 import com.android.server.UiServiceTestCase;
51 
52 import org.junit.After;
53 import org.junit.Before;
54 import org.junit.Ignore;
55 import org.junit.Test;
56 import org.junit.runner.RunWith;
57 
58 @SmallTest
59 @RunWith(AndroidTestingRunner.class)
60 @RunWithLooper
61 public class SliceManagerServiceTest extends UiServiceTestCase {
62 
63     private static final String AUTH = "com.android.services.uitests";
64     private static final Uri TEST_URI = Uri.parse("content://" + AUTH + "/path");
65 
66     private static final SliceSpec[] EMPTY_SPECS = new SliceSpec[]{
67     };
68 
69     private SliceManagerService mService;
70     private PinnedSliceState mCreatedSliceState;
71     private IBinder mToken = new Binder();
72     private TestableContext mContextSpy;
73 
74     @Before
setUp()75     public void setUp() {
76         LocalServices.addService(UsageStatsManagerInternal.class,
77                 mock(UsageStatsManagerInternal.class));
78         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
79 
80         mContextSpy = spy(mContext);
81         mService = spy(new SliceManagerService(mContextSpy, TestableLooper.get(this).getLooper()));
82         mCreatedSliceState = mock(PinnedSliceState.class);
83         doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI), anyString());
84     }
85 
86     @After
teardown()87     public void teardown() {
88         LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
89     }
90 
91     @Ignore("b/253871109")
92     @Test
testAddPinCreatesPinned()93     public void testAddPinCreatesPinned() throws RemoteException {
94         grantSlicePermission();
95         doReturn("pkg").when(mService).getDefaultHome(anyInt());
96 
97         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
98         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
99         verify(mService, times(1)).createPinnedSlice(eq(maybeAddUserId(TEST_URI, 0)), anyString());
100     }
101 
102     @Ignore("b/253871109")
103     @Test
testRemovePinDestroysPinned()104     public void testRemovePinDestroysPinned() throws RemoteException {
105         grantSlicePermission();
106         doReturn("pkg").when(mService).getDefaultHome(anyInt());
107 
108         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
109 
110         when(mCreatedSliceState.unpin(eq("pkg"), eq(mToken))).thenReturn(false);
111         mService.unpinSlice("pkg", TEST_URI, mToken);
112         verify(mCreatedSliceState, never()).destroy();
113     }
114 
115     @Ignore("b/253871109")
116     @Test
testCheckAutoGrantPermissions()117     public void testCheckAutoGrantPermissions() throws RemoteException {
118         String[] testPerms = new String[] {
119                 "perm1",
120                 "perm2",
121         };
122         when(mContextSpy.checkUriPermission(any(), anyInt(), anyInt(), anyInt()))
123                 .thenReturn(PERMISSION_DENIED);
124         when(mContextSpy.checkPermission("perm1", Process.myPid(), Process.myUid()))
125                 .thenReturn(PERMISSION_DENIED);
126         when(mContextSpy.checkPermission("perm2", Process.myPid(), Process.myUid()))
127                 .thenReturn(PERMISSION_GRANTED);
128         mService.checkSlicePermission(TEST_URI, mContext.getPackageName(),
129                 Process.myPid(), Process.myUid(), testPerms);
130 
131         verify(mContextSpy).checkPermission(eq("perm1"), eq(Process.myPid()), eq(Process.myUid()));
132         verify(mContextSpy).checkPermission(eq("perm2"), eq(Process.myPid()), eq(Process.myUid()));
133     }
134 
135     @Ignore("b/253871109")
136     @Test(expected = IllegalStateException.class)
testNoPinThrow()137     public void testNoPinThrow() throws Exception {
138         grantSlicePermission();
139         mService.getPinnedSpecs(TEST_URI, "pkg");
140     }
141 
142     @Ignore("b/253871109")
143     @Test
testGetPinnedSpecs()144     public void testGetPinnedSpecs() throws Exception {
145         grantSlicePermission();
146         SliceSpec[] specs = new SliceSpec[] {
147             new SliceSpec("Something", 1) };
148         mService.pinSlice("pkg", TEST_URI, specs, mToken);
149 
150         when(mCreatedSliceState.getSpecs()).thenReturn(specs);
151         assertEquals(specs, mService.getPinnedSpecs(TEST_URI, "pkg"));
152     }
153 
grantSlicePermission()154     private void grantSlicePermission() {
155         doReturn(PERMISSION_GRANTED).when(mService).checkSlicePermission(
156                 eq(TEST_URI), anyString(), anyInt(), anyInt(), any());
157         doReturn(PERMISSION_GRANTED).when(mService).checkAccess(
158                 anyString(), eq(TEST_URI), anyInt(), anyInt());
159     }
160 }
161