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 package com.android.settings.development; 17 18 import android.content.ContentResolver; 19 import android.content.Context; 20 import android.database.ContentObserver; 21 import android.debug.IAdbManager; 22 import android.net.ConnectivityManager; 23 import android.net.Network; 24 import android.net.NetworkCapabilities; 25 import android.net.Uri; 26 import android.os.Handler; 27 import android.os.Looper; 28 import android.os.RemoteException; 29 import android.os.ServiceManager; 30 import android.provider.Settings; 31 import android.util.Log; 32 import android.widget.Toast; 33 34 import androidx.preference.Preference; 35 import androidx.preference.PreferenceScreen; 36 37 import com.android.settings.R; 38 import com.android.settings.core.PreferenceControllerMixin; 39 import com.android.settings.widget.PrimarySwitchPreference; 40 import com.android.settingslib.core.lifecycle.Lifecycle; 41 import com.android.settingslib.core.lifecycle.LifecycleObserver; 42 import com.android.settingslib.core.lifecycle.events.OnPause; 43 import com.android.settingslib.core.lifecycle.events.OnResume; 44 import com.android.settingslib.development.DeveloperOptionsPreferenceController; 45 46 /** 47 * This controls the primary switch controller in the developer options page for 48 * "Wireless debugging". 49 */ 50 public class WirelessDebuggingPreferenceController extends DeveloperOptionsPreferenceController 51 implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin, 52 LifecycleObserver, OnResume, OnPause { 53 private static final String TAG = "WirelessDebugPrefCtrl"; 54 private final IAdbManager mAdbManager; 55 private final ContentResolver mContentResolver; 56 private final ContentObserver mSettingsObserver; 57 private final Handler mHandler = new Handler(Looper.getMainLooper()); 58 59 public static final String KEY_TOGGLE_ADB_WIRELESS = "toggle_adb_wireless"; 60 WirelessDebuggingPreferenceController(Context context, Lifecycle lifecycle)61 public WirelessDebuggingPreferenceController(Context context, Lifecycle lifecycle) { 62 super(context); 63 64 if (lifecycle != null) { 65 lifecycle.addObserver(this); 66 } 67 mAdbManager = IAdbManager.Stub.asInterface(ServiceManager.getService(Context.ADB_SERVICE)); 68 mSettingsObserver = new ContentObserver(mHandler) { 69 @Override 70 public void onChange(boolean selfChange, Uri uri) { 71 updateState(mPreference); 72 } 73 }; 74 mContentResolver = context.getContentResolver(); 75 } 76 77 @Override displayPreference(PreferenceScreen screen)78 public void displayPreference(PreferenceScreen screen) { 79 super.displayPreference(screen); 80 } 81 82 @Override isAvailable()83 public boolean isAvailable() { 84 try { 85 return mAdbManager.isAdbWifiSupported(); 86 } catch (RemoteException e) { 87 Log.e(TAG, "Unable to check if adb wifi is supported.", e); 88 } 89 90 return false; 91 } 92 93 @Override getPreferenceKey()94 public String getPreferenceKey() { 95 return KEY_TOGGLE_ADB_WIRELESS; 96 } 97 98 /** 99 * Called when developer options is enabled and the preference is available 100 */ 101 @Override onDeveloperOptionsSwitchEnabled()102 protected void onDeveloperOptionsSwitchEnabled() { 103 super.onDeveloperOptionsSwitchEnabled(); 104 mPreference.setEnabled(true); 105 } 106 107 /** 108 * Called when developer options is disabled and the preference is available 109 */ 110 @Override onDeveloperOptionsSwitchDisabled()111 protected void onDeveloperOptionsSwitchDisabled() { 112 super.onDeveloperOptionsSwitchDisabled(); 113 mPreference.setEnabled(false); 114 Settings.Global.putInt(mContext.getContentResolver(), 115 Settings.Global.ADB_WIFI_ENABLED, 116 AdbPreferenceController.ADB_SETTING_OFF); 117 } 118 119 @Override onResume()120 public void onResume() { 121 mContentResolver.registerContentObserver( 122 Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED), false, 123 mSettingsObserver); 124 } 125 126 @Override onPause()127 public void onPause() { 128 mContentResolver.unregisterContentObserver(mSettingsObserver); 129 } 130 131 @Override updateState(Preference preference)132 public void updateState(Preference preference) { 133 boolean enabled = Settings.Global.getInt(mContentResolver, 134 Settings.Global.ADB_WIFI_ENABLED, AdbPreferenceController.ADB_SETTING_OFF) 135 != AdbPreferenceController.ADB_SETTING_OFF; 136 ((PrimarySwitchPreference) preference).setChecked(enabled); 137 } 138 139 /** 140 * Returns true if connected to Wi-Fi network. 141 */ isWifiConnected(Context context)142 public static boolean isWifiConnected(Context context) { 143 ConnectivityManager cm = (ConnectivityManager) context.getSystemService( 144 Context.CONNECTIVITY_SERVICE); 145 if (cm == null) { 146 return false; 147 } 148 for (Network network : cm.getAllNetworks()) { 149 final NetworkCapabilities nc = cm.getNetworkCapabilities(network); 150 if (nc == null) { 151 continue; 152 } 153 if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { 154 return true; 155 } 156 } 157 return false; 158 } 159 160 @Override onPreferenceChange(Preference preference, Object newValue)161 public boolean onPreferenceChange(Preference preference, Object newValue) { 162 final boolean enabled = (Boolean) newValue; 163 if (enabled && !isWifiConnected(mContext)) { 164 // Cannot enable ADB over Wi-Fi if we're not connected to wifi. 165 Toast.makeText( 166 mContext, R.string.adb_wireless_no_network_msg, Toast.LENGTH_LONG) 167 .show(); 168 return false; 169 } 170 171 Settings.Global.putInt(mContext.getContentResolver(), 172 Settings.Global.ADB_WIFI_ENABLED, 173 enabled ? AdbPreferenceController.ADB_SETTING_ON 174 : AdbPreferenceController.ADB_SETTING_OFF); 175 return true; 176 } 177 } 178