1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tests.statsd.framework.appnopermission; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.assertThrows; 21 22 import android.app.PendingIntent; 23 import android.app.StatsManager; 24 import android.app.StatsManager.StatsUnavailableException; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.Intent; 28 import androidx.test.InstrumentationRegistry; 29 import com.android.internal.os.StatsdConfigProto.StatsdConfig; 30 import org.junit.Test; 31 32 public class StatsdPermissionTest { 33 /** 34 * Broadcast receiver to test registration of a FetchOperation. 35 */ 36 public static final class SimpleReceiver extends BroadcastReceiver { 37 @Override onReceive(Context mContext, Intent intent)38 public void onReceive(Context mContext, Intent intent) {} 39 } 40 41 /** 42 * Tests that calling apis without permissions throws the appropriate exception. 43 */ 44 @Test testApisThrowExceptionWithoutPermission()45 public void testApisThrowExceptionWithoutPermission() throws Exception { 46 Context context = InstrumentationRegistry.getTargetContext(); 47 StatsManager statsManager = context.getSystemService(StatsManager.class); 48 StatsUnavailableException e = assertThrows(StatsManager.StatsUnavailableException.class, 49 () 50 -> statsManager.addConfig(1234, 51 StatsdConfig.newBuilder() 52 .setId(1234) 53 .addAllowedLogSource("foo") 54 .build() 55 .toByteArray())); 56 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 57 58 e = assertThrows( 59 StatsManager.StatsUnavailableException.class, () -> statsManager.removeConfig(1234)); 60 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 61 62 e = assertThrows( 63 StatsManager.StatsUnavailableException.class, () -> statsManager.getReports(1234)); 64 // expectations are: 65 // - for Android T+ receive IllegalStateException 66 // - for previous versions receive SecurityExceptions 67 assertThat(e.getCause().getClass()). 68 isAnyOf(SecurityException.class, IllegalStateException.class); 69 70 e = assertThrows( 71 StatsManager.StatsUnavailableException.class, () -> statsManager.getStatsMetadata()); 72 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 73 74 e = assertThrows(StatsManager.StatsUnavailableException.class, 75 () -> statsManager.getRegisteredExperimentIds()); 76 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 77 78 PendingIntent pi = PendingIntent.getBroadcast( 79 context, 1, new Intent(context, SimpleReceiver.class), PendingIntent.FLAG_MUTABLE); 80 81 e = assertThrows(StatsManager.StatsUnavailableException.class, 82 () -> statsManager.setBroadcastSubscriber(pi, 123, 0)); 83 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 84 85 e = assertThrows(StatsManager.StatsUnavailableException.class, 86 () -> statsManager.setBroadcastSubscriber(null, 123, 0)); 87 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 88 89 e = assertThrows(StatsManager.StatsUnavailableException.class, 90 () -> statsManager.setFetchReportsOperation(pi, 123)); 91 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 92 93 e = assertThrows(StatsManager.StatsUnavailableException.class, 94 () -> statsManager.setFetchReportsOperation(null, 123)); 95 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 96 97 e = assertThrows(StatsManager.StatsUnavailableException.class, 98 () -> statsManager.setActiveConfigsChangedOperation(pi)); 99 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 100 101 e = assertThrows(StatsManager.StatsUnavailableException.class, 102 () -> statsManager.setActiveConfigsChangedOperation(null)); 103 assertThat(e).hasCauseThat().isInstanceOf(SecurityException.class); 104 105 // Setting a pull atom callback is not tested because it is oneway, 106 // so the security exception would not propagate to the client. 107 } 108 } 109