Home | History | Annotate | Download | only in cts
      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