1 /*
2  * Copyright (C) 2020 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.settings.cts;
18 
19 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20 import static android.provider.Settings.Secure;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import static org.junit.Assume.assumeFalse;
25 
26 import android.app.slice.Slice;
27 import android.app.slice.SliceManager;
28 import android.content.ComponentName;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.pm.PackageManager;
32 import android.content.pm.PackageManager.NameNotFoundException;
33 import android.content.pm.ResolveInfo;
34 import android.net.Uri;
35 import android.net.wifi.WifiManager;
36 import android.os.Process;
37 import android.text.TextUtils;
38 import android.util.Log;
39 
40 import androidx.slice.SliceConvert;
41 import androidx.slice.SliceMetadata;
42 import androidx.slice.core.SliceAction;
43 import androidx.test.InstrumentationRegistry;
44 import androidx.test.runner.AndroidJUnit4;
45 
46 import org.junit.After;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 
51 import java.util.Collections;
52 import java.util.List;
53 
54 @RunWith(AndroidJUnit4.class)
55 public class WifiSliceTest {
56   private static final String TAG = "WifiSliceTest";
57 
58   private static final Uri WIFI_SLICE_URI =
59           Uri.parse("content://android.settings.slices/action/wifi");
60 
61   private static final String ACTION_ASSIST = "android.intent.action.ASSIST";
62   private static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
63   private static final String CATEGORY_DEFAULT = "android.intent.category.DEFAULT";
64   private static final String FEATURE_VOICE_RECOGNIZERS = "android.software.voice_recognizers";
65   private static final String ASSISTANT = "assistant";
66 
67   private final Context mContext = InstrumentationRegistry.getContext();
68   private final SliceManager mSliceManager = mContext.getSystemService(SliceManager.class);
69   private final boolean mHasVoiceRecognizersFeature =
70           mContext.getPackageManager().hasSystemFeature(FEATURE_VOICE_RECOGNIZERS);
71 
72   private Slice mWifiSlice;
73   private String mAssistant;
74 
75   @Before
setUp()76   public void setUp() throws Exception {
77     assumeFalse("Skipping test: Auto does not support provider android.settings.slices", isCar());
78     assumeFalse("Skipping test: TV does not support provider android.settings.slices", isTv());
79     assumeFalse(
80         "Skipping test: Watch does not support provider android.settings.slices", isWatch());
81     mWifiSlice = mSliceManager.bindSlice(WIFI_SLICE_URI, Collections.emptySet());
82     mAssistant = Secure.getString(mContext.getContentResolver(), ASSISTANT);
83   }
84 
85   @After
tearDown()86   public void tearDown() {
87     final String assistant = Secure.getString(mContext.getContentResolver(), ASSISTANT);
88     if (!TextUtils.equals(mAssistant, assistant)) {
89       Secure.putString(mContext.getContentResolver(), ASSISTANT, mAssistant);
90     }
91   }
92 
93   @Test
wifiSliceToggle_changeWifiState()94   public void wifiSliceToggle_changeWifiState() {
95     SliceMetadata mWifiSliceMetadata =
96             SliceMetadata.from(mContext, SliceConvert.wrap(mWifiSlice, mContext));
97     List<SliceAction> wifiSliceActions = mWifiSliceMetadata.getToggles();
98     if (wifiSliceActions.size() != 0) {
99       SliceAction toggleAction = wifiSliceActions.get(0);
100 
101       toggleAction.setChecked(true);
102       assertThat(toggleAction.isChecked()).isEqualTo(isWifiEnabled());
103 
104       toggleAction.setChecked(false);
105       assertThat(toggleAction.isChecked()).isEqualTo(isWifiEnabled());
106     }
107   }
108 
109   @Test
wifiSlice_hasCorrectUri()110   public void wifiSlice_hasCorrectUri() {
111     assertThat(mWifiSlice.getUri()).isEqualTo(WIFI_SLICE_URI);
112   }
113 
114   @Test
wifiSlice_grantedPermissionToDefaultAssistant()115   public void wifiSlice_grantedPermissionToDefaultAssistant() throws NameNotFoundException {
116     if (!mHasVoiceRecognizersFeature) {
117       Log.i(TAG, "The device doesn't support feature: " + FEATURE_VOICE_RECOGNIZERS);
118       return;
119     }
120     final PackageManager pm = mContext.getPackageManager();
121     final Intent requestDefaultAssistant =
122             new Intent(ACTION_ASSIST).addCategory(CATEGORY_DEFAULT);
123 
124     final List<ResolveInfo> infos = pm.queryIntentActivities(requestDefaultAssistant, 0);
125 
126     if (!infos.isEmpty()) {
127       final String packageName;
128       if (!TextUtils.isEmpty(mAssistant)) {
129         packageName = ComponentName.unflattenFromString(mAssistant).getPackageName();
130         Log.i(TAG, "Default assistant: " + packageName);
131       } else {
132         packageName = infos.get(0).activityInfo.packageName;
133         Log.i(TAG, "Set assistant: " + packageName);
134         Secure.putString(mContext.getContentResolver(), ASSISTANT,
135                 new ComponentName(packageName, infos.get(0).activityInfo.name).flattenToString());
136       }
137       final int testPid = Process.myPid();
138       final int testUid = pm.getPackageUid(packageName, 0);
139 
140       assertThat(mSliceManager.checkSlicePermission(WIFI_SLICE_URI, testPid, testUid))
141               .isEqualTo(PERMISSION_GRANTED);
142     }
143   }
144 
145   @Test
wifiSlice_grantedPermissionToDefaultVoiceAssistant()146   public void wifiSlice_grantedPermissionToDefaultVoiceAssistant() throws NameNotFoundException {
147     if (!mHasVoiceRecognizersFeature) {
148       Log.i(TAG, "The device doesn't support feature: " + FEATURE_VOICE_RECOGNIZERS);
149       return;
150     }
151     final PackageManager pm = mContext.getPackageManager();
152     final Intent requestDefaultAssistant =
153             new Intent(ACTION_VOICE_ASSIST).addCategory(CATEGORY_DEFAULT);
154 
155     final ResolveInfo info = pm.resolveActivity(requestDefaultAssistant, 0);
156 
157     if (info != null) {
158       final String packageName;
159       if (!TextUtils.isEmpty(mAssistant)) {
160         packageName = ComponentName.unflattenFromString(mAssistant).getPackageName();
161         Log.i(TAG, "Default assistant: " + packageName);
162       } else {
163         packageName = info.activityInfo.packageName;
164         Log.i(TAG, "Set assistant: " + packageName);
165         Secure.putString(mContext.getContentResolver(), ASSISTANT,
166                 new ComponentName(packageName, info.activityInfo.name).flattenToString());
167       }
168       final int testPid = Process.myPid();
169       final int testUid = pm.getPackageUid(packageName, 0);
170 
171       assertThat(mSliceManager.checkSlicePermission(WIFI_SLICE_URI, testPid, testUid))
172               .isEqualTo(PERMISSION_GRANTED);
173     }
174   }
175 
isCar()176   private boolean isCar() {
177     PackageManager pm = mContext.getPackageManager();
178     return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
179   }
180 
isTv()181   private boolean isTv() {
182     PackageManager pm = mContext.getPackageManager();
183     return pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
184             && pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
185   }
186 
isWatch()187   private boolean isWatch() {
188     return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
189   }
190 
isWifiEnabled()191   private boolean isWifiEnabled() {
192     final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
193     return wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED
194             || wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING;
195   }
196 
197 }
198