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