WifiP2pSettings.java revision c08caf7a339677a7806e80f940d4d54690e4de92
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 OnClickListener mCancelConnectListener; 76 private WifiP2pPeer mSelectedWifiPeer; 77 78 private boolean mWifiP2pEnabled; 79 private boolean mWifiP2pSearching; 80 private int mConnectedDevices; 81 82 private PreferenceGroup mPeersGroup; 83 private Preference mThisDevicePref; 84 85 private static final int DIALOG_DISCONNECT = 1; 86 private static final int DIALOG_CANCEL_CONNECT = 2; 87 88 private WifiP2pDevice mThisDevice; 89 private WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); 90 91 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 92 @Override 93 public void onReceive(Context context, Intent intent) { 94 String action = intent.getAction(); 95 96 if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) { 97 mWifiP2pEnabled = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 98 WifiP2pManager.WIFI_P2P_STATE_DISABLED) == WifiP2pManager.WIFI_P2P_STATE_ENABLED; 99 handleP2pStateChanged(); 100 } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { 101 if (mWifiP2pManager != null) { 102 mWifiP2pManager.requestPeers(mChannel, WifiP2pSettings.this); 103 } 104 } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { 105 if (mWifiP2pManager == null) return; 106 NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra( 107 WifiP2pManager.EXTRA_NETWORK_INFO); 108 if (networkInfo.isConnected()) { 109 if (DBG) Log.d(TAG, "Connected"); 110 } else { 111 //start a search when we are disconnected 112 startSearch(); 113 } 114 } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) { 115 mThisDevice = (WifiP2pDevice) intent.getParcelableExtra( 116 WifiP2pManager.EXTRA_WIFI_P2P_DEVICE); 117 if (DBG) Log.d(TAG, "Update device info: " + mThisDevice); 118 updateDevicePref(); 119 } else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) { 120 int discoveryState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, 121 WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); 122 if (DBG) Log.d(TAG, "Discovery state changed: " + discoveryState); 123 if (discoveryState == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) { 124 updateSearchMenu(true); 125 } else { 126 updateSearchMenu(false); 127 } 128 } 129 } 130 }; 131 132 @Override 133 public void onCreate(Bundle icicle) { 134 super.onCreate(icicle); 135 addPreferencesFromResource(R.xml.wifi_p2p_settings); 136 137 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 138 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 139 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 140 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 141 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION); 142 143 final Activity activity = getActivity(); 144 mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); 145 if (mWifiP2pManager != null) { 146 mChannel = mWifiP2pManager.initialize(activity, getActivity().getMainLooper(), null); 147 if (mChannel == null) { 148 //Failure to set up connection 149 Log.e(TAG, "Failed to set up connection with wifi p2p service"); 150 mWifiP2pManager = null; 151 } 152 } else { 153 Log.e(TAG, "mWifiP2pManager is null !"); 154 } 155 156 //disconnect dialog listener 157 mDisconnectListener = new OnClickListener() { 158 @Override 159 public void onClick(DialogInterface dialog, int which) { 160 if (which == DialogInterface.BUTTON_POSITIVE) { 161 if (mWifiP2pManager != null) { 162 mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() { 163 public void onSuccess() { 164 if (DBG) Log.d(TAG, " remove group success"); 165 } 166 public void onFailure(int reason) { 167 if (DBG) Log.d(TAG, " remove group fail " + reason); 168 } 169 }); 170 } 171 } 172 } 173 }; 174 175 //cancel connect dialog listener 176 mCancelConnectListener = new OnClickListener() { 177 @Override 178 public void onClick(DialogInterface dialog, int which) { 179 if (which == DialogInterface.BUTTON_POSITIVE) { 180 if (mWifiP2pManager != null) { 181 mWifiP2pManager.cancelConnect(mChannel, 182 new WifiP2pManager.ActionListener() { 183 public void onSuccess() { 184 if (DBG) Log.d(TAG, " cancel connect success"); 185 } 186 public void onFailure(int reason) { 187 if (DBG) Log.d(TAG, " cancel connect fail " + reason); 188 } 189 }); 190 } 191 } 192 } 193 }; 194 195 setHasOptionsMenu(true); 196 197 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 198 preferenceScreen.removeAll(); 199 200 preferenceScreen.setOrderingAsAdded(true); 201 mThisDevicePref = new Preference(getActivity()); 202 preferenceScreen.addPreference(mThisDevicePref); 203 204 mPeersGroup = new PreferenceCategory(getActivity()); 205 mPeersGroup.setTitle(R.string.wifi_p2p_peer_devices); 206 } 207 208 @Override 209 public void onResume() { 210 super.onResume(); 211 getActivity().registerReceiver(mReceiver, mIntentFilter); 212 mWifiP2pManager.requestPeers(mChannel, WifiP2pSettings.this); 213 } 214 215 @Override 216 public void onPause() { 217 super.onPause(); 218 mWifiP2pManager.stopPeerDiscovery(mChannel, null); 219 getActivity().unregisterReceiver(mReceiver); 220 } 221 222 @Override 223 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 224 int textId = mWifiP2pSearching ? R.string.wifi_p2p_menu_searching : 225 R.string.wifi_p2p_menu_search; 226 menu.add(Menu.NONE, MENU_ID_SEARCH, 0, textId) 227 .setEnabled(mWifiP2pEnabled) 228 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 229 menu.add(Menu.NONE, MENU_ID_RENAME, 0, R.string.wifi_p2p_menu_rename) 230 .setEnabled(mWifiP2pEnabled) 231 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 232 super.onCreateOptionsMenu(menu, inflater); 233 } 234 235 @Override 236 public void onPrepareOptionsMenu(Menu menu) { 237 MenuItem searchMenu = menu.findItem(MENU_ID_SEARCH); 238 MenuItem renameMenu = menu.findItem(MENU_ID_RENAME); 239 if (mWifiP2pEnabled) { 240 searchMenu.setEnabled(true); 241 renameMenu.setEnabled(true); 242 } else { 243 searchMenu.setEnabled(false); 244 renameMenu.setEnabled(false); 245 } 246 247 if (mWifiP2pSearching) { 248 searchMenu.setTitle(R.string.wifi_p2p_menu_searching); 249 } else { 250 searchMenu.setTitle(R.string.wifi_p2p_menu_search); 251 } 252 } 253 254 @Override 255 public boolean onOptionsItemSelected(MenuItem item) { 256 switch (item.getItemId()) { 257 case MENU_ID_SEARCH: 258 startSearch(); 259 return true; 260 case MENU_ID_RENAME: 261 //TODO: handle rename 262 return true; 263 } 264 return super.onOptionsItemSelected(item); 265 } 266 267 @Override 268 public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { 269 if (preference instanceof WifiP2pPeer) { 270 mSelectedWifiPeer = (WifiP2pPeer) preference; 271 if (mSelectedWifiPeer.device.status == WifiP2pDevice.CONNECTED) { 272 showDialog(DIALOG_DISCONNECT); 273 } else if (mSelectedWifiPeer.device.status == WifiP2pDevice.INVITED) { 274 showDialog(DIALOG_CANCEL_CONNECT); 275 } else { 276 WifiP2pConfig config = new WifiP2pConfig(); 277 config.deviceAddress = mSelectedWifiPeer.device.deviceAddress; 278 279 int forceWps = SystemProperties.getInt("wifidirect.wps", -1); 280 281 if (forceWps != -1) { 282 config.wps.setup = forceWps; 283 } else { 284 if (mSelectedWifiPeer.device.wpsPbcSupported()) { 285 config.wps.setup = WpsInfo.PBC; 286 } else if (mSelectedWifiPeer.device.wpsKeypadSupported()) { 287 config.wps.setup = WpsInfo.KEYPAD; 288 } else { 289 config.wps.setup = WpsInfo.DISPLAY; 290 } 291 } 292 293 mWifiP2pManager.connect(mChannel, config, 294 new WifiP2pManager.ActionListener() { 295 public void onSuccess() { 296 if (DBG) Log.d(TAG, " connect success"); 297 } 298 public void onFailure(int reason) { 299 Log.e(TAG, " connect fail " + reason); 300 Toast.makeText(getActivity(), 301 R.string.wifi_p2p_failed_connect_message, 302 Toast.LENGTH_SHORT).show(); 303 } 304 }); 305 } 306 } 307 return super.onPreferenceTreeClick(screen, preference); 308 } 309 310 @Override 311 public Dialog onCreateDialog(int id) { 312 if (id == DIALOG_DISCONNECT) { 313 int stringId = (mConnectedDevices > 1) ? R.string.wifi_p2p_disconnect_multiple_message : 314 R.string.wifi_p2p_disconnect_message; 315 String deviceName = TextUtils.isEmpty(mSelectedWifiPeer.device.deviceName) ? 316 mSelectedWifiPeer.device.deviceAddress : 317 mSelectedWifiPeer.device.deviceName; 318 AlertDialog dialog = new AlertDialog.Builder(getActivity()) 319 .setTitle(R.string.wifi_p2p_disconnect_title) 320 .setMessage(getActivity().getString(stringId, deviceName)) 321 .setPositiveButton(getActivity().getString(R.string.dlg_ok), mDisconnectListener) 322 .setNegativeButton(getActivity().getString(R.string.dlg_cancel), null) 323 .create(); 324 return dialog; 325 } else if (id == DIALOG_CANCEL_CONNECT) { 326 int stringId = R.string.wifi_p2p_cancel_connect_message; 327 String deviceName = TextUtils.isEmpty(mSelectedWifiPeer.device.deviceName) ? 328 mSelectedWifiPeer.device.deviceAddress : 329 mSelectedWifiPeer.device.deviceName; 330 331 AlertDialog dialog = new AlertDialog.Builder(getActivity()) 332 .setTitle(R.string.wifi_p2p_cancel_connect_title) 333 .setMessage(getActivity().getString(stringId, deviceName)) 334 .setPositiveButton(getActivity().getString(R.string.dlg_ok), mCancelConnectListener) 335 .setNegativeButton(getActivity().getString(R.string.dlg_cancel), null) 336 .create(); 337 return dialog; 338 } 339 return null; 340 } 341 342 public void onPeersAvailable(WifiP2pDeviceList peers) { 343 mPeersGroup.removeAll(); 344 345 mPeers = peers; 346 mConnectedDevices = 0; 347 for (WifiP2pDevice peer: peers.getDeviceList()) { 348 if (DBG) Log.d(TAG, " peer " + peer); 349 mPeersGroup.addPreference(new WifiP2pPeer(getActivity(), peer)); 350 if (peer.status == WifiP2pDevice.CONNECTED) mConnectedDevices++; 351 } 352 if (DBG) Log.d(TAG, " mConnectedDevices " + mConnectedDevices); 353 } 354 355 private void handleP2pStateChanged() { 356 updateSearchMenu(false); 357 if (mWifiP2pEnabled) { 358 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 359 preferenceScreen.removeAll(); 360 361 preferenceScreen.setOrderingAsAdded(true); 362 preferenceScreen.addPreference(mThisDevicePref); 363 364 mPeersGroup.setEnabled(true); 365 preferenceScreen.addPreference(mPeersGroup); 366 } 367 } 368 369 private void updateSearchMenu(boolean searching) { 370 mWifiP2pSearching = searching; 371 Activity activity = getActivity(); 372 if (activity != null) activity.invalidateOptionsMenu(); 373 } 374 375 private void startSearch() { 376 if (mWifiP2pManager != null && !mWifiP2pSearching) { 377 mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() { 378 public void onSuccess() { 379 } 380 public void onFailure(int reason) { 381 if (DBG) Log.d(TAG, " discover fail " + reason); 382 } 383 }); 384 } 385 } 386 387 private void updateDevicePref() { 388 if (mThisDevice != null) { 389 if (TextUtils.isEmpty(mThisDevice.deviceName)) { 390 mThisDevicePref.setTitle(mThisDevice.deviceAddress); 391 } else { 392 mThisDevicePref.setTitle(mThisDevice.deviceName); 393 } 394 395 mThisDevicePref.setPersistent(false); 396 mThisDevicePref.setEnabled(true); 397 mThisDevicePref.setSelectable(false); 398 } 399 } 400} 401