[adbwifi] Add qstile for wireless debugging.

Bug: 153275926

Test: make RunSettingsRoboTests ROBOTEST_FILTER=WirelessDebuggingTest
Change-Id: I6b381a7e29beec5c9c345b374e127caabdb674db
(cherry picked from commit 0c23d39f94)
Exempt-From-Owner-Approval: cherry-pick
This commit is contained in:
Joshua Duong
2020-04-07 00:17:17 -07:00
parent afaf654a77
commit 0f3eba36f2
5 changed files with 349 additions and 2 deletions

View File

@@ -3107,6 +3107,19 @@
android:value="true"/>
</service>
<service
android:name=".development.qstile.DevelopmentTiles$WirelessDebugging"
android:label="@string/enable_adb_wireless"
android:icon="@drawable/tile_icon_debugging_wireless"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:enabled="false">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
<meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true"/>
</service>
<activity
android:name=".HelpTrampoline"
android:exported="true"

View File

@@ -0,0 +1,28 @@
<!--
Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M19,10.3L19,16A7,7 0,0 1,5 16L5,10.3ZM7.5,14.5l0.8,0.8a5.3,5.3 0,0 1,7.4 0l0.8,-0.8A6.3,6.3 0,0 0,7.5 14.5ZM10.8,17.8L12,19l1.2,-1.2A1.6,1.6 0,0 0,10.8 17.8ZM9.1,16.1l0.9,0.9a2.7,2.7 0,0 1,4 0l0.9,-0.9A4.3,4.3 0,0 0,9.1 16.1Z"/>
<path
android:fillColor="#FFFFFFFF"
android:pathData="M15.6,3.9l1.1,-2c0.1,-0.2 0.1,-0.4 -0.1,-0.5a0.5,0.5 0,0 0,-0.6 0.1L14.8,3.6a6.8,6.8 0,0 0,-5.6 0L8,1.5a0.5,0.5 0,0 0,-0.6 -0.1c-0.2,0.1 -0.2,0.3 -0.1,0.5l1.1,2A7.1,7.1 0,0 0,5 9.3L19,9.3A7.1,7.1 0,0 0,15.6 3.9ZM8.8,7.6A0.9,0.9 0,0 1,8 6.8,0.9 0.9,0 0,1 8.8,6a0.8,0.8 0,1 1,0 1.6ZM15.2,7.6a0.8,0.8 0,1 1,0 -1.6,0.9 0.9,0 0,1 0.8,0.8A0.9,0.9 0,0 1,15.2 7.6Z"/>
</vector>

View File

@@ -135,7 +135,10 @@ public class WirelessDebuggingPreferenceController extends DeveloperOptionsPrefe
((MasterSwitchPreference) preference).setChecked(enabled);
}
static boolean isWifiConnected(Context context) {
/**
* Returns true if connected to Wi-Fi network.
*/
public static boolean isWifiConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
Context.CONNECTIVITY_SERVICE);
if (cm != null) {

View File

@@ -16,13 +16,21 @@
package com.android.settings.development.qstile;
import static com.android.settings.development.AdbPreferenceController.ADB_SETTING_OFF;
import static com.android.settings.development.AdbPreferenceController.ADB_SETTING_ON;
import android.app.KeyguardManager;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.hardware.SensorPrivacyManager;
import android.app.KeyguardManager;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -41,6 +49,8 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.app.LocalePicker;
import com.android.internal.statusbar.IStatusBarService;
import com.android.settings.R;
import com.android.settings.development.WirelessDebuggingPreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
@@ -349,4 +359,77 @@ public abstract class DevelopmentTiles extends TileService {
mSensorPrivacyManager.setSensorPrivacy(isEnabled);
}
}
/**
* Tile to control the "Wireless debugging" developer setting
*/
public static class WirelessDebugging extends DevelopmentTiles {
private Context mContext;
private KeyguardManager mKeyguardManager;
private Toast mToast;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
refresh();
}
};
@Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
mKeyguardManager = (KeyguardManager) mContext.getSystemService(
Context.KEYGUARD_SERVICE);
mToast = Toast.makeText(mContext, R.string.adb_wireless_no_network_msg,
Toast.LENGTH_LONG);
}
@Override
public void onStartListening() {
super.onStartListening();
getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED), false,
mSettingsObserver);
}
@Override
public void onStopListening() {
super.onStopListening();
getContentResolver().unregisterContentObserver(mSettingsObserver);
}
@Override
protected boolean isEnabled() {
return isAdbWifiEnabled();
}
@Override
public void setIsEnabled(boolean isEnabled) {
// Don't allow Wireless Debugging to be enabled from the lock screen.
if (isEnabled && mKeyguardManager.isKeyguardLocked()) {
return;
}
// Show error toast if not connected to Wi-Fi
if (isEnabled && !WirelessDebuggingPreferenceController.isWifiConnected(mContext)) {
// Close quick shade
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
mToast.show();
return;
}
writeAdbWifiSetting(isEnabled);
}
private boolean isAdbWifiEnabled() {
return Settings.Global.getInt(getContentResolver(), Settings.Global.ADB_WIFI_ENABLED,
ADB_SETTING_OFF) != ADB_SETTING_OFF;
}
protected void writeAdbWifiSetting(boolean enabled) {
Settings.Global.putInt(getContentResolver(), Settings.Global.ADB_WIFI_ENABLED,
enabled ? ADB_SETTING_ON : ADB_SETTING_OFF);
}
}
}

View File

@@ -0,0 +1,220 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.development.qstile;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings.Global;
import android.widget.Toast;
import com.android.settings.testutils.shadow.ShadowWirelessDebuggingPreferenceController;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowWirelessDebuggingPreferenceController.class})
public class WirelessDebuggingTest {
@Mock
private Toast mToast;
@Mock
private KeyguardManager mKeyguardManager;
private Context mContext;
private DevelopmentTiles.WirelessDebugging mWirelessDebugging;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mWirelessDebugging = spy(new DevelopmentTiles.WirelessDebugging());
doReturn(mContext.getContentResolver()).when(mWirelessDebugging).getContentResolver();
ReflectionHelpers.setField(mWirelessDebugging, "mKeyguardManager", mKeyguardManager);
ReflectionHelpers.setField(mWirelessDebugging, "mToast", mToast);
}
@After
public void tearDown() {
ShadowWirelessDebuggingPreferenceController.reset();
}
@Test
public void adbWifiEnabled_shouldReturnEnabled() {
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 1 /* setting enabled */);
assertThat(mWirelessDebugging.isEnabled()).isTrue();
}
@Test
public void adbWifiDisabled_shouldReturnDisabled() {
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 0 /* setting disabled */);
assertThat(mWirelessDebugging.isEnabled()).isFalse();
}
@Test
public void setIsEnabled_false_keyguardUnlocked_WifiDisconnected_shouldDisableAdbWifi() {
// Precondition: set the tile to enabled
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 1 /* setting enabled */);
// Unlocked keyguard
doReturn(false).when(mKeyguardManager).isKeyguardLocked();
// Wifi disconnected
ShadowWirelessDebuggingPreferenceController.setIsWifiConnected(false);
mWirelessDebugging.setIsEnabled(false);
assertThat(mWirelessDebugging.isEnabled()).isFalse();
}
@Test
public void setIsEnabled_false_keyguardLocked_WifiDisconnected_shouldDisableAdbWifi() {
// Precondition: set the tile to enabled
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 1 /* setting enabled */);
// Locked keyguard
doReturn(true).when(mKeyguardManager).isKeyguardLocked();
// Wifi disconnected
ShadowWirelessDebuggingPreferenceController.setIsWifiConnected(false);
mWirelessDebugging.setIsEnabled(false);
assertThat(mWirelessDebugging.isEnabled()).isFalse();
}
@Test
public void setIsEnabled_false_keyguardUnlocked_WifiConnected_shouldDisableAdbWifi() {
// Precondition: set the tile to enabled
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 1 /* setting enabled */);
// Unlocked keyguard
doReturn(false).when(mKeyguardManager).isKeyguardLocked();
// Wifi connected
ShadowWirelessDebuggingPreferenceController.setIsWifiConnected(true);
mWirelessDebugging.setIsEnabled(false);
assertThat(mWirelessDebugging.isEnabled()).isFalse();
}
@Test
public void setIsEnabled_false_keyguardLocked_WifiConnected_shouldDisableAdbWifi() {
// Precondition: set the tile to enabled
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 1 /* setting enabled */);
// Locked keyguard
doReturn(true).when(mKeyguardManager).isKeyguardLocked();
// Wifi connected
ShadowWirelessDebuggingPreferenceController.setIsWifiConnected(true);
mWirelessDebugging.setIsEnabled(false);
assertThat(mWirelessDebugging.isEnabled()).isFalse();
}
@Test
public void setIsEnabled_true_keyguardUnlocked_WifiDisconnected_shouldDisableAdbWifi() {
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mWirelessDebugging).sendBroadcast(intentCaptor.capture());
// Precondition: set the tile to disabled
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 0 /* setting enabled */);
// Unlocked keyguard
doReturn(false).when(mKeyguardManager).isKeyguardLocked();
// Wifi disconnected
ShadowWirelessDebuggingPreferenceController.setIsWifiConnected(false);
mWirelessDebugging.setIsEnabled(true);
assertThat(mWirelessDebugging.isEnabled()).isFalse();
// The notification shade should be hidden by sending a broadcast to SysUI
// so the toast can be seen
verify(mWirelessDebugging, times(1)).sendBroadcast(eq(intentCaptor.getValue()));
assertThat(intentCaptor.getValue().getAction())
.isEqualTo(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
// Should also get a toast that wifi is not connected
verify(mToast).show();
}
@Test
public void setIsEnabled_true_keyguardLocked_WifiDisconnected_shouldDisableAdbWifi() {
// Precondition: set the tile to disabled
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 0 /* setting enabled */);
// Locked keyguard
doReturn(true).when(mKeyguardManager).isKeyguardLocked();
// Wifi disconnected
ShadowWirelessDebuggingPreferenceController.setIsWifiConnected(false);
mWirelessDebugging.setIsEnabled(true);
// Shouldn't be able to enable wireless debugging from locked screen
assertThat(mWirelessDebugging.isEnabled()).isFalse();
}
@Test
public void setIsEnabled_true_keyguardUnlocked_WifiConnected_shouldDisableAdbWifi() {
// Precondition: set the tile to disabled
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 0 /* setting enabled */);
// Unlocked keyguard
doReturn(false).when(mKeyguardManager).isKeyguardLocked();
// Wifi connected
ShadowWirelessDebuggingPreferenceController.setIsWifiConnected(true);
mWirelessDebugging.setIsEnabled(true);
assertThat(mWirelessDebugging.isEnabled()).isTrue();
}
@Test
public void setIsEnabled_true_keyguardLocked_WifiConnected_shouldDisableAdbWifi() {
// Precondition: set the tile to disabled
Global.putInt(mContext.getContentResolver(),
Global.ADB_WIFI_ENABLED, 0 /* setting enabled */);
// Locked keyguard
doReturn(true).when(mKeyguardManager).isKeyguardLocked();
// Wifi connected
ShadowWirelessDebuggingPreferenceController.setIsWifiConnected(true);
mWirelessDebugging.setIsEnabled(true);
// Shouldn't be able to enable wireless debugging from locked screen
assertThat(mWirelessDebugging.isEnabled()).isFalse();
}
}