diff options
author | Joshua Duong <joshuaduong@google.com> | 2020-04-07 00:17:17 -0700 |
---|---|---|
committer | Joshua Duong <joshuaduong@google.com> | 2020-04-10 19:12:40 +0000 |
commit | 0f3eba36f2b056bb0b586288d03895ab4e40a23f (patch) | |
tree | fa40561c8c7a2ece0877e1cffa62c96e0d54874e | |
parent | afaf654a77226d0bcf79e4e798b8d3ebd0b4d1a0 (diff) | |
download | packages_apps_Settings-0f3eba36f2b056bb0b586288d03895ab4e40a23f.tar.gz packages_apps_Settings-0f3eba36f2b056bb0b586288d03895ab4e40a23f.tar.bz2 packages_apps_Settings-0f3eba36f2b056bb0b586288d03895ab4e40a23f.zip |
[adbwifi] Add qstile for wireless debugging.
Bug: 153275926
Test: make RunSettingsRoboTests ROBOTEST_FILTER=WirelessDebuggingTest
Change-Id: I6b381a7e29beec5c9c345b374e127caabdb674db
(cherry picked from commit 0c23d39f941c50d00cc8a9b5f5ee100ee5c17b48)
Exempt-From-Owner-Approval: cherry-pick
5 files changed, 349 insertions, 2 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 07bc06cf35..b494d35fcd 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -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" diff --git a/res/drawable/tile_icon_debugging_wireless.xml b/res/drawable/tile_icon_debugging_wireless.xml new file mode 100644 index 0000000000..4f0f56c679 --- /dev/null +++ b/res/drawable/tile_icon_debugging_wireless.xml @@ -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> diff --git a/src/com/android/settings/development/WirelessDebuggingPreferenceController.java b/src/com/android/settings/development/WirelessDebuggingPreferenceController.java index 55fd074cc1..a3daede3ca 100644 --- a/src/com/android/settings/development/WirelessDebuggingPreferenceController.java +++ b/src/com/android/settings/development/WirelessDebuggingPreferenceController.java @@ -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) { diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java index 8f06750e5c..916c6c9291 100644 --- a/src/com/android/settings/development/qstile/DevelopmentTiles.java +++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java @@ -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); + } + } } diff --git a/tests/robotests/src/com/android/settings/development/qstile/WirelessDebuggingTest.java b/tests/robotests/src/com/android/settings/development/qstile/WirelessDebuggingTest.java new file mode 100644 index 0000000000..9230ca8f24 --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/qstile/WirelessDebuggingTest.java @@ -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(); + } +} |