1 /* 2 * Copyright (C) 2018 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 android.slice.cts; 16 17 import static org.junit.Assert.assertEquals; 18 import static org.junit.Assert.assertTrue; 19 import static org.mockito.ArgumentMatchers.any; 20 import static org.mockito.ArgumentMatchers.eq; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.timeout; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import android.app.Instrumentation; 27 import android.app.PendingIntent; 28 import android.app.slice.Slice; 29 import android.app.slice.SliceItem; 30 import android.app.slice.SliceManager; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.net.Uri; 34 import android.os.ParcelFileDescriptor; 35 36 import androidx.test.InstrumentationRegistry; 37 import androidx.test.runner.AndroidJUnit4; 38 39 import org.junit.After; 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.stubbing.Answer; 44 45 import java.io.BufferedReader; 46 import java.io.InputStreamReader; 47 import java.util.ArrayList; 48 import java.util.Collections; 49 import java.util.List; 50 51 @RunWith(AndroidJUnit4.class) 52 public class SliceManagerTest { 53 54 private static final Uri BASE_URI = Uri.parse("content://android.slice.cts.local/main"); 55 private final Context mContext = InstrumentationRegistry.getContext(); 56 private final SliceManager mSliceManager = mContext.getSystemService(SliceManager.class); 57 58 @Before 59 public void setup() { 60 LocalSliceProvider.sProxy = mock(SliceProvider.class); 61 try { 62 mSliceManager.unpinSlice(BASE_URI); 63 } catch (Exception e) { 64 } 65 } 66 67 @After 68 public void teardown() throws Exception { 69 try { 70 mSliceManager.unpinSlice(BASE_URI); 71 } catch (Exception e) { 72 } 73 } 74 75 @Test 76 public void testPinSlice() throws Exception { 77 mSliceManager.pinSlice(BASE_URI, Collections.emptySet()); 78 79 verify(LocalSliceProvider.sProxy, timeout(2000)).onSlicePinned(eq(BASE_URI)); 80 } 81 82 @Test 83 public void testUnpinSlice() throws Exception { 84 mSliceManager.pinSlice(BASE_URI, Collections.emptySet()); 85 86 verify(LocalSliceProvider.sProxy, timeout(2000)).onSlicePinned(eq(BASE_URI)); 87 88 mSliceManager.unpinSlice(BASE_URI); 89 90 verify(LocalSliceProvider.sProxy, timeout(2000)).onSliceUnpinned(eq(BASE_URI)); 91 } 92 93 @Test 94 public void testPinList() { 95 Uri uri = BASE_URI; 96 Uri longerUri = uri.buildUpon().appendPath("something").build(); 97 try { 98 mSliceManager.pinSlice(uri, Collections.emptySet()); 99 mSliceManager.pinSlice(longerUri, Collections.emptySet()); 100 verify(LocalSliceProvider.sProxy, timeout(2000)).onSlicePinned(eq(longerUri)); 101 102 List<Uri> uris = mSliceManager.getPinnedSlices(); 103 assertEquals(2, uris.size()); 104 assertTrue(uris.contains(uri)); 105 assertTrue(uris.contains(longerUri)); 106 } finally { 107 mSliceManager.unpinSlice(uri); 108 mSliceManager.unpinSlice(longerUri); 109 } 110 } 111 112 @Test 113 public void testMapIntentToUri() { 114 Intent intent = new Intent("android.slice.cts.action.TEST_ACTION"); 115 intent.setPackage("android.slice.cts"); 116 intent.putExtra("path", "intent"); 117 118 when(LocalSliceProvider.sProxy.onMapIntentToUri(any())).then( 119 (Answer<Uri>) invocation -> BASE_URI.buildUpon().path( 120 ((Intent) invocation.getArguments()[0]).getStringExtra("path")).build()); 121 122 Uri uri = mSliceManager.mapIntentToUri(intent); 123 124 assertEquals(BASE_URI.buildUpon().path("intent").build(), uri); 125 verify(LocalSliceProvider.sProxy).onMapIntentToUri(eq(intent)); 126 } 127 128 @Test 129 public void testOnCreatePermissionSlice() { 130 LocalSliceProvider.sAnswer = invocation -> { 131 throw new SecurityException("No slices allowed"); 132 }; 133 try { 134 Uri uri = BASE_URI.buildUpon().path("permission").build(); 135 PendingIntent intent = PendingIntent.getBroadcast(mContext, 0, new Intent(""), 0); 136 137 when(LocalSliceProvider.sProxy.onCreatePermissionRequest(any())).thenReturn(intent); 138 139 Slice s = mSliceManager.bindSlice(uri, Collections.emptySet()); 140 141 /// Make sure we get a callback for creating the intent. 142 verify(LocalSliceProvider.sProxy).onCreatePermissionRequest(eq(uri)); 143 // Verify the intent we get back is the one we returned. 144 PendingIntent i = findAction(s); 145 assertTrue(intent == i); 146 } finally { 147 LocalSliceProvider.sAnswer = null; 148 } 149 } 150 151 private PendingIntent findAction(Slice s) { 152 for (SliceItem item : s.getItems()) { 153 if (SliceItem.FORMAT_SLICE.equals(item.getFormat())) { 154 return findAction(item.getSlice()); 155 } 156 if (SliceItem.FORMAT_ACTION.equals(item.getFormat())) { 157 return item.getAction(); 158 } 159 } 160 return null; 161 } 162 163 public static String getDefaultLauncher() throws Exception { 164 final String PREFIX = "Launcher: ComponentInfo{"; 165 final String POSTFIX = "}"; 166 for (String s : runShellCommand("cmd shortcut get-default-launcher")) { 167 if (s.startsWith(PREFIX) && s.endsWith(POSTFIX)) { 168 return s.substring(PREFIX.length(), s.length() - POSTFIX.length()); 169 } 170 } 171 throw new Exception("Default launcher not found"); 172 } 173 174 public static ArrayList<String> runShellCommand(String command) throws Exception { 175 ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation() 176 .executeShellCommand(command); 177 178 ArrayList<String> ret = new ArrayList<>(); 179 // Read the input stream fully. 180 try (BufferedReader r = new BufferedReader( 181 new InputStreamReader(new ParcelFileDescriptor.AutoCloseInputStream(pfd)))) { 182 String line; 183 while ((line = r.readLine()) != null) { 184 ret.add(line); 185 } 186 } 187 return ret; 188 } 189 190 public static Instrumentation getInstrumentation() { 191 return InstrumentationRegistry.getInstrumentation(); 192 } 193 194 } 195