WifiP2pSettings.java revision 3a14bafcf6792e14b3d74a591af39c9d62a4cc26
1/* 2 * Copyright (C) 2011 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 17package com.android.settings.wifi.p2p; 18 19import android.app.ActionBar; 20import android.app.Activity; 21import android.app.AlertDialog; 22import android.app.Dialog; 23import android.content.BroadcastReceiver; 24import android.content.Context; 25import android.content.DialogInterface; 26import android.content.DialogInterface.OnClickListener; 27import android.content.Intent; 28import android.content.IntentFilter; 29import android.net.NetworkInfo; 30import android.net.wifi.p2p.WifiP2pConfig; 31import android.net.wifi.p2p.WifiP2pDevice; 32import android.net.wifi.p2p.WifiP2pDeviceList; 33import android.net.wifi.p2p.WifiP2pManager; 34import android.net.wifi.p2p.WifiP2pManager.PeerListListener; 35import android.net.wifi.WpsInfo; 36import android.os.Bundle; 37import android.os.Handler; 38import android.os.SystemProperties; 39import android.preference.Preference; 40import android.preference.PreferenceActivity; 41import android.preference.PreferenceCategory; 42import android.preference.PreferenceGroup; 43import android.preference.PreferenceScreen; 44import android.text.TextUtils; 45import android.util.Log; 46import android.view.Gravity; 47import android.view.Menu; 48import android.view.MenuInflater; 49import android.view.MenuItem; 50import android.widget.Switch; 51import android.widget.Toast; 52 53import com.android.settings.R; 54import com.android.settings.SettingsPreferenceFragment; 55 56import java.util.Arrays; 57import java.util.List; 58import java.util.Collection; 59 60/* 61 * Displays Wi-fi p2p settings UI 62 */ 63public class WifiP2pSettings extends SettingsPreferenceFragment 64 implements PeerListListener { 65 66 private static final String TAG = "WifiP2pSettings"; 67 private static final boolean DBG = false; 68 private static final int MENU_ID_SEARCH = Menu.FIRST; 69 private static final int MENU_ID_RENAME = Menu.FIRST + 1; 70 71 private final IntentFilter mIntentFilter = new IntentFilter(); 72 private WifiP2pManager mWifiP2pManager; 73 private WifiP2pManager.Channel mChannel; 74 private OnClickListener mDisconnectListener; 75 private WifiP2pPeer mSelectedWifiPeer; 76 77 private boolean mWifiP2pEnabled; 78 private boolean mWifiP2pSearching; 79 private int mConnectedDevices; 80 81 private PreferenceGroup mPeersGroup; 82 private Preference mThisDevicePref; 83 84 private static final int DIALOG_DISCONNECT = 1; 85 86 private WifiP2pDevice mThisDevice; 87 private WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); 88 89 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 90 @Override 91 public void onReceive(Context context, Intent intent) { 92 String action = intent.getAction(); 93 94 if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) { 95 mWifiP2pEnabled = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 96 WifiP2pManager.WIFI_P2P_STATE_DISABLED) == WifiP2pManager.WIFI_P2P_STATE_ENABLED; 97 handleP2pStateChanged(); 98 } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { 99 if (mWifiP2pManager != null) { 100 mWifiP2pManager.requestPeers(mChannel, WifiP2pSettings.this); 101 } 102 } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { 103 if (mWifiP2pManager == null) return; 104 NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra( 105 WifiP2pManager.EXTRA_NETWORK_INFO); 106 if (networkInfo.isConnected()) { 107 if (DBG) Log.d(TAG, "Connected"); 108 } else { 109 //start a search when we are disconnected 110 startSearch(); 111 } 112 } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) { 113 mThisDevice = (WifiP2pDevice) intent.getParcelableExtra( 114 WifiP2pManager.EXTRA_WIFI_P2P_DEVICE); 115 if (DBG) Log.d(TAG, "Update device info: " + mThisDevice); 116 updateDevicePref(); 117 } else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) { 118 int discoveryState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, 119 WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); 120 if (DBG) Log.d(TAG, "Discovery state changed: " + discoveryState); 121 if (discoveryState == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) { 122 updateSearchMenu(true); 123 } else { 124 updateSearchMenu(false); 125 } 126 } 127 } 128 }; 129 130 @Override 131 public void onCreate(Bundle icicle) { 132 super.onCreate(icicle); 133 addPreferencesFromResource(R.xml.wifi_p2p_settings); 134 135 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 136 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 137 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 138 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 139 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION); 140 141 final Activity activity = getActivity(); 142 mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); 143 if (mWifiP2pManager != null) { 144 mChannel = mWifiP2pManager.initialize(activity, getActivity().getMainLooper(), null); 145 if (mChannel == null) { 146 //Failure to set up connection 147 Log.e(TAG, "Failed to set up connection with wifi p2p service"); 148 mWifiP2pManager = null; 149 } 150 } else { 151 Log.e(TAG, "mWifiP2pManager is null !"); 152 } 153 154 //disconnect dialog listener 155 mDisconnectListener = new OnClickListener() { 156 @Override 157 public void onClick(DialogInterface dialog, int which) { 158 if (which == DialogInterface.BUTTON_POSITIVE) { 159 if (mWifiP2pManager != null) { 160 mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() { 161 public void onSuccess() { 162 if (DBG) Log.d(TAG, " remove group success"); 163 } 164 public void onFailure(int reason) { 165 if (DBG) Log.d(TAG, " remove group fail " + reason); 166 } 167 }); 168 } 169 } 170 } 171 }; 172 173 setHasOptionsMenu(true); 174 175 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 176 preferenceScreen.removeAll(); 177 178 preferenceScreen.setOrderingAsAdded(true); 179 mThisDevicePref = new Preference(getActivity()); 180 preferenceScreen.addPreference(mThisDevicePref); 181 182 mPeersGroup = new PreferenceCategory(getActivity()); 183 mPeersGroup.setTitle(R.string.wifi_p2p_peer_devices); 184 } 185 186 @Override 187 public void onResume() { 188 super.onResume(); 189 getActivity().registerReceiver(mReceiver, mIntentFilter); 190 mWifiP2pManager.requestPeers(mChannel, WifiP2pSettings.this); 191 } 192 193 @Override 194 public void onPause() { 195 super.onPause(); 196 mWifiP2pManager.stopPeerDiscovery(mChannel, null); 197 getActivity().unregisterReceiver(mReceiver); 198 } 199 200 @Override 201 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 202 int textId = mWifiP2pSearching ? R.string.wifi_p2p_menu_searching : 203 R.string.wifi_p2p_menu_search; 204 menu.add(Menu.NONE, MENU_ID_SEARCH, 0, textId) 205 .setEnabled(mWifiP2pEnabled) 206 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 207 menu.add(Menu.NONE, MENU_ID_RENAME, 0, R.string.wifi_p2p_menu_rename) 208 .setEnabled(mWifiP2pEnabled) 209 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 210 super.onCreateOptionsMenu(menu, inflater); 211 } 212 213 @Override 214 public void onPrepareOptionsMenu(Menu menu) { 215 MenuItem searchMenu = menu.findItem(MENU_ID_SEARCH); 216 MenuItem renameMenu = menu.findItem(MENU_ID_RENAME); 217 if (mWifiP2pEnabled) { 218 searchMenu.setEnabled(true); 219 renameMenu.setEnabled(true); 220 } else { 221 searchMenu.setEnabled(false); 222 renameMenu.setEnabled(false); 223 } 224 225 if (mWifiP2pSearching) { 226 searchMenu.setTitle(R.string.wifi_p2p_menu_searching); 227 } else { 228 searchMenu.setTitle(R.string.wifi_p2p_menu_search); 229 } 230 } 231 232 @Override 233 public boolean onOptionsItemSelected(MenuItem item) { 234 switch (item.getItemId()) { 235 case MENU_ID_SEARCH: 236 startSearch(); 237 return true; 238 case MENU_ID_RENAME: 239 //TODO: handle rename 240 return true; 241 } 242 return super.onOptionsItemSelected(item); 243 } 244 245 @Override 246 public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { 247 if (preference instanceof WifiP2pPeer) { 248 mSelectedWifiPeer = (WifiP2pPeer) preference; 249 if (mSelectedWifiPeer.device.status == WifiP2pDevice.CONNECTED) { 250 showDialog(DIALOG_DISCONNECT); 251 } else { 252 WifiP2pConfig config = new WifiP2pConfig(); 253 config.deviceAddress = mSelectedWifiPeer.device.deviceAddress; 254 255 int forceWps = SystemProperties.getInt("wifidirect.wps", -1); 256 257 if (forceWps != -1) { 258 config.wps.setup = forceWps; 259 } else { 260 if (mSelectedWifiPeer.device.wpsPbcSupported()) { 261 config.wps.setup = WpsInfo.PBC; 262 } else if (mSelectedWifiPeer.device.wpsKeypadSupported()) { 263 config.wps.setup = WpsInfo.KEYPAD; 264 } else { 265 config.wps.setup = WpsInfo.DISPLAY; 266 } 267 } 268 269 mWifiP2pManager.connect(mChannel, config, 270 new WifiP2pManager.ActionListener() { 271 public void onSuccess() { 272 if (DBG) Log.d(TAG, " connect success"); 273 } 274 public void onFailure(int reason) { 275 Log.e(TAG, " connect fail " + reason); 276 Toast.makeText(getActivity(), 277 R.string.wifi_p2p_failed_connect_message, 278 Toast.LENGTH_SHORT).show(); 279 } 280 }); 281 } 282 } 283 return super.onPreferenceTreeClick(screen, preference); 284 } 285 286 @Override 287 public Dialog onCreateDialog(int id) { 288 if (id == DIALOG_DISCONNECT) { 289 int stringId = (mConnectedDevices > 1) ? R.string.wifi_p2p_disconnect_multiple_message : 290 R.string.wifi_p2p_disconnect_message; 291 String deviceName = TextUtils.isEmpty(mSelectedWifiPeer.device.deviceName) ? 292 mSelectedWifiPeer.device.deviceAddress : 293 mSelectedWifiPeer.device.deviceName; 294 AlertDialog dialog = new AlertDialog.Builder(getActivity()) 295 .setTitle(R.string.wifi_p2p_disconnect_title) 296 .setMessage(getActivity().getString(stringId, deviceName)) 297 .setPositiveButton(getActivity().getString(R.string.dlg_ok), mDisconnectListener) 298 .setNegativeButton(getActivity().getString(R.string.dlg_cancel), null) 299 .create(); 300 return dialog; 301 } 302 return null; 303 } 304 305 public void onPeersAvailable(WifiP2pDeviceList peers) { 306 mPeersGroup.removeAll(); 307 308 mPeers = peers; 309 mConnectedDevices = 0; 310 for (WifiP2pDevice peer: peers.getDeviceList()) { 311 if (DBG) Log.d(TAG, " peer " + peer); 312 mPeersGroup.addPreference(new WifiP2pPeer(getActivity(), peer)); 313 if (peer.status == WifiP2pDevice.CONNECTED) mConnectedDevices++; 314 } 315 if (DBG) Log.d(TAG, " mConnectedDevices " + mConnectedDevices); 316 } 317 318 private void handleP2pStateChanged() { 319 updateSearchMenu(false); 320 if (mWifiP2pEnabled) { 321 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 322 preferenceScreen.removeAll(); 323 324 preferenceScreen.setOrderingAsAdded(true); 325 preferenceScreen.addPreference(mThisDevicePref); 326 327 mPeersGroup.setEnabled(true); 328 preferenceScreen.addPreference(mPeersGroup); 329 } 330 } 331 332 private void updateSearchMenu(boolean searching) { 333 mWifiP2pSearching = searching; 334 Activity activity = getActivity(); 335 if (activity != null) activity.invalidateOptionsMenu(); 336 } 337 338 private void startSearch() { 339 if (mWifiP2pManager != null && !mWifiP2pSearching) { 340 mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() { 341 public void onSuccess() { 342 } 343 public void onFailure(int reason) { 344 if (DBG) Log.d(TAG, " discover fail " + reason); 345 } 346 }); 347 } 348 } 349 350 private void updateDevicePref() { 351 if (mThisDevice != null) { 352 if (TextUtils.isEmpty(mThisDevice.deviceName)) { 353 mThisDevicePref.setTitle(mThisDevice.deviceAddress); 354 } else { 355 mThisDevicePref.setTitle(mThisDevice.deviceName); 356 } 357 358 mThisDevicePref.setPersistent(false); 359 mThisDevicePref.setEnabled(true); 360 mThisDevicePref.setSelectable(false); 361 } 362 } 363} 364