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 17 package com.android.settings.wifi.p2p; 18 19 import android.app.Activity; 20 import android.app.Dialog; 21 import android.app.settings.SettingsEnums; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.content.DialogInterface.OnClickListener; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.net.NetworkInfo; 29 import android.net.wifi.WpsInfo; 30 import android.net.wifi.p2p.WifiP2pConfig; 31 import android.net.wifi.p2p.WifiP2pDevice; 32 import android.net.wifi.p2p.WifiP2pDeviceList; 33 import android.net.wifi.p2p.WifiP2pGroup; 34 import android.net.wifi.p2p.WifiP2pGroupList; 35 import android.net.wifi.p2p.WifiP2pInfo; 36 import android.net.wifi.p2p.WifiP2pManager; 37 import android.net.wifi.p2p.WifiP2pManager.DeviceInfoListener; 38 import android.net.wifi.p2p.WifiP2pManager.PeerListListener; 39 import android.net.wifi.p2p.WifiP2pManager.PersistentGroupInfoListener; 40 import android.os.Bundle; 41 import android.sysprop.TelephonyProperties; 42 import android.text.InputFilter; 43 import android.text.TextUtils; 44 import android.util.Log; 45 import android.view.LayoutInflater; 46 import android.view.Menu; 47 import android.view.MenuInflater; 48 import android.view.MenuItem; 49 import android.view.View; 50 import android.view.ViewGroup; 51 import android.widget.EditText; 52 import android.widget.Toast; 53 54 import androidx.annotation.VisibleForTesting; 55 import androidx.appcompat.app.AlertDialog; 56 import androidx.preference.Preference; 57 import androidx.preference.PreferenceScreen; 58 59 import com.android.settings.R; 60 import com.android.settings.dashboard.DashboardFragment; 61 import com.android.settingslib.core.AbstractPreferenceController; 62 63 import java.util.ArrayList; 64 import java.util.List; 65 66 /* 67 * Displays Wi-fi p2p settings UI 68 */ 69 public class WifiP2pSettings extends DashboardFragment 70 implements PersistentGroupInfoListener, PeerListListener, DeviceInfoListener { 71 72 private static final String TAG = "WifiP2pSettings"; 73 private static final boolean DBG = false; 74 @VisibleForTesting static final int MENU_ID_SEARCH = Menu.FIRST; 75 @VisibleForTesting static final int MENU_ID_RENAME = Menu.FIRST + 1; 76 77 private final IntentFilter mIntentFilter = new IntentFilter(); 78 @VisibleForTesting WifiP2pManager mWifiP2pManager; 79 @VisibleForTesting static WifiP2pManager.Channel sChannel; 80 @VisibleForTesting OnClickListener mRenameListener; 81 @VisibleForTesting OnClickListener mDisconnectListener; 82 @VisibleForTesting OnClickListener mCancelConnectListener; 83 @VisibleForTesting OnClickListener mDeleteGroupListener; 84 @VisibleForTesting WifiP2pPeer mSelectedWifiPeer; 85 @VisibleForTesting WifiP2pPersistentGroup mSelectedGroup; 86 @VisibleForTesting String mSelectedGroupName; 87 private EditText mDeviceNameText; 88 89 private boolean mWifiP2pEnabled; 90 @VisibleForTesting boolean mWifiP2pSearching; 91 @VisibleForTesting int mConnectedDevices; 92 @VisibleForTesting boolean mLastGroupFormed = false; 93 private boolean mIsIgnoreInitConnectionInfoCallback = false; 94 95 @VisibleForTesting P2pPeerCategoryPreferenceController mPeerCategoryController; 96 @VisibleForTesting P2pPersistentCategoryPreferenceController mPersistentCategoryController; 97 @VisibleForTesting P2pThisDevicePreferenceController mThisDevicePreferenceController; 98 99 @VisibleForTesting static final int DIALOG_DISCONNECT = 1; 100 @VisibleForTesting static final int DIALOG_CANCEL_CONNECT = 2; 101 @VisibleForTesting static final int DIALOG_RENAME = 3; 102 @VisibleForTesting static final int DIALOG_DELETE_GROUP = 4; 103 104 @VisibleForTesting static final String SAVE_DIALOG_PEER = "PEER_STATE"; 105 @VisibleForTesting static final String SAVE_DEVICE_NAME = "DEV_NAME"; 106 @VisibleForTesting static final String SAVE_SELECTED_GROUP = "GROUP_NAME"; 107 108 private WifiP2pDevice mThisDevice; 109 private WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); 110 111 @VisibleForTesting String mSavedDeviceName; 112 113 @VisibleForTesting 114 final BroadcastReceiver mReceiver = new BroadcastReceiver() { 115 @Override 116 public void onReceive(Context context, Intent intent) { 117 String action = intent.getAction(); 118 119 if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) { 120 mWifiP2pEnabled = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 121 WifiP2pManager.WIFI_P2P_STATE_DISABLED) == WifiP2pManager.WIFI_P2P_STATE_ENABLED; 122 handleP2pStateChanged(); 123 } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { 124 mPeers = (WifiP2pDeviceList) intent.getParcelableExtra( 125 WifiP2pManager.EXTRA_P2P_DEVICE_LIST); 126 handlePeersChanged(); 127 } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { 128 if (mWifiP2pManager == null) return; 129 NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra( 130 WifiP2pManager.EXTRA_NETWORK_INFO); 131 WifiP2pInfo wifip2pinfo = (WifiP2pInfo) intent.getParcelableExtra( 132 WifiP2pManager.EXTRA_WIFI_P2P_INFO); 133 if (networkInfo.isConnected()) { 134 if (DBG) Log.d(TAG, "Connected"); 135 } else if (mLastGroupFormed != true) { 136 //start a search when we are disconnected 137 //but not on group removed broadcast event 138 startSearch(); 139 } 140 mLastGroupFormed = wifip2pinfo.groupFormed; 141 mIsIgnoreInitConnectionInfoCallback = true; 142 } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) { 143 WifiP2pDevice device = 144 (WifiP2pDevice) intent.getExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE); 145 if (device != null && device.status == WifiP2pDevice.UNAVAILABLE) { 146 return; 147 } 148 // Do not use WifiP2pManager.EXTRA_WIFI_P2P_DEVICE from the extras, as the system 149 // broadcast does not contain the device's MAC. 150 // Requesting our own device info as an app holding the NETWORK_SETTINGS permission 151 // ensures that the MAC address will be available in the result. 152 if (DBG) Log.d(TAG, "This device changed. Requesting device info."); 153 if (mWifiP2pManager != null && sChannel != null) { 154 mWifiP2pManager.requestDeviceInfo(sChannel, WifiP2pSettings.this); 155 } 156 } else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) { 157 int discoveryState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, 158 WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); 159 if (DBG) Log.d(TAG, "Discovery state changed: " + discoveryState); 160 if (discoveryState == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) { 161 updateSearchMenu(true); 162 } else { 163 updateSearchMenu(false); 164 } 165 } else if (WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED.equals(action)) { 166 if (mWifiP2pManager != null && sChannel != null) { 167 mWifiP2pManager.requestPersistentGroupInfo(sChannel, WifiP2pSettings.this); 168 } 169 } 170 } 171 }; 172 173 @Override getLogTag()174 protected String getLogTag() { 175 return TAG; 176 } 177 178 @Override getPreferenceScreenResId()179 protected int getPreferenceScreenResId() { 180 return R.xml.wifi_p2p_settings; 181 } 182 183 @Override getMetricsCategory()184 public int getMetricsCategory() { 185 return SettingsEnums.WIFI_P2P; 186 } 187 188 @Override getHelpResource()189 public int getHelpResource() { 190 return R.string.help_url_wifi_p2p; 191 } 192 193 @Override createPreferenceControllers(Context context)194 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) { 195 final List<AbstractPreferenceController> controllers = new ArrayList<>(); 196 mPersistentCategoryController = 197 new P2pPersistentCategoryPreferenceController(context); 198 mPeerCategoryController = 199 new P2pPeerCategoryPreferenceController(context); 200 mThisDevicePreferenceController = new P2pThisDevicePreferenceController(context); 201 controllers.add(mPersistentCategoryController); 202 controllers.add(mPeerCategoryController); 203 controllers.add(mThisDevicePreferenceController); 204 return controllers; 205 } 206 207 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)208 public View onCreateView(LayoutInflater inflater, ViewGroup container, 209 Bundle savedInstanceState) { 210 final View root = super.onCreateView(inflater, container, savedInstanceState); 211 212 final Activity activity = getActivity(); 213 if (mWifiP2pManager == null) { 214 mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); 215 } 216 217 if (mWifiP2pManager != null) { 218 if (!initChannel()) { 219 //Failure to set up connection 220 Log.e(TAG, "Failed to set up connection with wifi p2p service"); 221 mWifiP2pManager = null; 222 } 223 } else { 224 Log.e(TAG, "mWifiP2pManager is null !"); 225 } 226 227 if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_DIALOG_PEER)) { 228 WifiP2pDevice device = savedInstanceState.getParcelable(SAVE_DIALOG_PEER); 229 mSelectedWifiPeer = new WifiP2pPeer(getPrefContext(), device); 230 } 231 if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_DEVICE_NAME)) { 232 mSavedDeviceName = savedInstanceState.getString(SAVE_DEVICE_NAME); 233 } 234 if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_SELECTED_GROUP)) { 235 mSelectedGroupName = savedInstanceState.getString(SAVE_SELECTED_GROUP); 236 } 237 238 mRenameListener = new OnClickListener() { 239 @Override 240 public void onClick(DialogInterface dialog, int which) { 241 if (which == DialogInterface.BUTTON_POSITIVE) { 242 if (mWifiP2pManager != null && sChannel != null) { 243 String name = mDeviceNameText.getText().toString(); 244 if (name != null) { 245 for (int i = 0; i < name.length(); i++) { 246 char cur = name.charAt(i); 247 if(!Character.isDigit(cur) && !Character.isLetter(cur) 248 && cur != '-' && cur != '_' && cur != ' ') { 249 Toast.makeText(getActivity(), 250 R.string.wifi_p2p_failed_rename_message, 251 Toast.LENGTH_LONG).show(); 252 return; 253 } 254 } 255 } 256 mWifiP2pManager.setDeviceName(sChannel, 257 mDeviceNameText.getText().toString(), 258 new WifiP2pManager.ActionListener() { 259 public void onSuccess() { 260 if (DBG) Log.d(TAG, " device rename success"); 261 } 262 public void onFailure(int reason) { 263 Toast.makeText(getActivity(), 264 R.string.wifi_p2p_failed_rename_message, 265 Toast.LENGTH_LONG).show(); 266 } 267 }); 268 } 269 } 270 } 271 }; 272 273 //disconnect dialog listener 274 mDisconnectListener = new OnClickListener() { 275 @Override 276 public void onClick(DialogInterface dialog, int which) { 277 if (which == DialogInterface.BUTTON_POSITIVE) { 278 if (mWifiP2pManager != null && sChannel != null) { 279 mWifiP2pManager.removeGroup(sChannel, new WifiP2pManager.ActionListener() { 280 public void onSuccess() { 281 if (DBG) Log.d(TAG, " remove group success"); 282 } 283 public void onFailure(int reason) { 284 if (DBG) Log.d(TAG, " remove group fail " + reason); 285 } 286 }); 287 } 288 } 289 } 290 }; 291 292 //cancel connect dialog listener 293 mCancelConnectListener = new OnClickListener() { 294 @Override 295 public void onClick(DialogInterface dialog, int which) { 296 if (which == DialogInterface.BUTTON_POSITIVE) { 297 if (mWifiP2pManager != null && sChannel != null) { 298 mWifiP2pManager.cancelConnect(sChannel, 299 new WifiP2pManager.ActionListener() { 300 public void onSuccess() { 301 if (DBG) Log.d(TAG, " cancel connect success"); 302 } 303 public void onFailure(int reason) { 304 if (DBG) Log.d(TAG, " cancel connect fail " + reason); 305 } 306 }); 307 } 308 } 309 } 310 }; 311 312 //delete persistent group dialog listener 313 mDeleteGroupListener = new OnClickListener() { 314 @Override 315 public void onClick(DialogInterface dialog, int which) { 316 if (which == DialogInterface.BUTTON_POSITIVE) { 317 if (mWifiP2pManager != null && sChannel != null) { 318 if (mSelectedGroup != null) { 319 if (DBG) Log.d(TAG, " deleting group " + mSelectedGroup.getGroupName()); 320 mWifiP2pManager.deletePersistentGroup(sChannel, 321 mSelectedGroup.getNetworkId(), 322 new WifiP2pManager.ActionListener() { 323 public void onSuccess() { 324 if (DBG) Log.d(TAG, " delete group success"); 325 } 326 327 public void onFailure(int reason) { 328 if (DBG) Log.d(TAG, " delete group fail " + reason); 329 } 330 }); 331 mSelectedGroup = null; 332 } else { 333 if (DBG) Log.w(TAG, " No selected group to delete!"); 334 } 335 } 336 } else if (which == DialogInterface.BUTTON_NEGATIVE) { 337 if (DBG) { 338 Log.d(TAG, " forgetting selected group " + mSelectedGroup.getGroupName()); 339 } 340 mSelectedGroup = null; 341 } 342 } 343 }; 344 return root; 345 } 346 347 @Override onStart()348 public void onStart() { 349 super.onStart(); 350 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 351 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 352 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 353 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 354 mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION); 355 mIntentFilter.addAction(WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED); 356 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 357 if (mWifiP2pManager != null && initChannel()) { 358 // Register receiver after make sure channel exist 359 getActivity().registerReceiver(mReceiver, mIntentFilter); 360 mWifiP2pManager.requestPeers(sChannel, WifiP2pSettings.this); 361 mWifiP2pManager.requestDeviceInfo(sChannel, WifiP2pSettings.this); 362 mIsIgnoreInitConnectionInfoCallback = false; 363 } 364 } 365 366 @Override onStop()367 public void onStop() { 368 super.onStop(); 369 if (mWifiP2pManager != null && sChannel != null) { 370 mWifiP2pManager.stopPeerDiscovery(sChannel, null); 371 if (!mLastGroupFormed) { 372 // Close the channel when p2p doesn't connected. 373 sChannel.close(); 374 sChannel = null; 375 } 376 } 377 getActivity().unregisterReceiver(mReceiver); 378 } 379 380 @Override onCreateOptionsMenu(Menu menu, MenuInflater inflater)381 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 382 int textId = mWifiP2pSearching ? R.string.wifi_p2p_menu_searching : 383 R.string.wifi_p2p_menu_search; 384 menu.add(Menu.NONE, MENU_ID_SEARCH, 0, textId) 385 .setEnabled(mWifiP2pEnabled); 386 menu.add(Menu.NONE, MENU_ID_RENAME, 0, R.string.wifi_p2p_menu_rename) 387 .setEnabled(mWifiP2pEnabled); 388 super.onCreateOptionsMenu(menu, inflater); 389 } 390 391 @Override onPrepareOptionsMenu(Menu menu)392 public void onPrepareOptionsMenu(Menu menu) { 393 MenuItem searchMenu = menu.findItem(MENU_ID_SEARCH); 394 MenuItem renameMenu = menu.findItem(MENU_ID_RENAME); 395 if (mWifiP2pEnabled) { 396 searchMenu.setEnabled(true); 397 renameMenu.setEnabled(true); 398 } else { 399 searchMenu.setEnabled(false); 400 renameMenu.setEnabled(false); 401 } 402 403 if (mWifiP2pSearching) { 404 searchMenu.setTitle(R.string.wifi_p2p_menu_searching); 405 } else { 406 searchMenu.setTitle(R.string.wifi_p2p_menu_search); 407 } 408 } 409 410 @Override onOptionsItemSelected(MenuItem item)411 public boolean onOptionsItemSelected(MenuItem item) { 412 switch (item.getItemId()) { 413 case MENU_ID_SEARCH: 414 startSearch(); 415 return true; 416 case MENU_ID_RENAME: 417 showDialog(DIALOG_RENAME); 418 return true; 419 } 420 return super.onOptionsItemSelected(item); 421 } 422 423 @Override onPreferenceTreeClick(Preference preference)424 public boolean onPreferenceTreeClick(Preference preference) { 425 if (preference instanceof WifiP2pPeer) { 426 mSelectedWifiPeer = (WifiP2pPeer) preference; 427 if (mSelectedWifiPeer.device.status == WifiP2pDevice.CONNECTED) { 428 showDialog(DIALOG_DISCONNECT); 429 } else if (mSelectedWifiPeer.device.status == WifiP2pDevice.INVITED) { 430 showDialog(DIALOG_CANCEL_CONNECT); 431 } else { 432 WifiP2pConfig config = new WifiP2pConfig(); 433 config.deviceAddress = mSelectedWifiPeer.device.deviceAddress; 434 435 int forceWps = TelephonyProperties.wps_info().orElse(-1); 436 437 if (forceWps != -1) { 438 config.wps.setup = forceWps; 439 } else { 440 if (mSelectedWifiPeer.device.wpsPbcSupported()) { 441 config.wps.setup = WpsInfo.PBC; 442 } else if (mSelectedWifiPeer.device.wpsKeypadSupported()) { 443 config.wps.setup = WpsInfo.KEYPAD; 444 } else { 445 config.wps.setup = WpsInfo.DISPLAY; 446 } 447 } 448 if (mWifiP2pManager != null && sChannel != null) { 449 mWifiP2pManager.connect(sChannel, config, 450 new WifiP2pManager.ActionListener() { 451 public void onSuccess() { 452 if (DBG) Log.d(TAG, " connect success"); 453 } 454 public void onFailure(int reason) { 455 Log.e(TAG, " connect fail " + reason); 456 Toast.makeText(getActivity(), 457 R.string.wifi_p2p_failed_connect_message, 458 Toast.LENGTH_SHORT).show(); 459 } 460 }); 461 } 462 } 463 } else if (preference instanceof WifiP2pPersistentGroup) { 464 mSelectedGroup = (WifiP2pPersistentGroup) preference; 465 showDialog(DIALOG_DELETE_GROUP); 466 } 467 return super.onPreferenceTreeClick(preference); 468 } 469 470 @Override onCreateDialog(int id)471 public Dialog onCreateDialog(int id) { 472 if (id == DIALOG_DISCONNECT) { 473 String deviceName = TextUtils.isEmpty(mSelectedWifiPeer.device.deviceName) ? 474 mSelectedWifiPeer.device.deviceAddress : 475 mSelectedWifiPeer.device.deviceName; 476 String msg; 477 if (mConnectedDevices > 1) { 478 msg = getActivity().getString(R.string.wifi_p2p_disconnect_multiple_message, 479 deviceName, mConnectedDevices - 1); 480 } else { 481 msg = getActivity().getString(R.string.wifi_p2p_disconnect_message, deviceName); 482 } 483 AlertDialog dialog = new AlertDialog.Builder(getActivity()) 484 .setTitle(R.string.wifi_p2p_disconnect_title) 485 .setMessage(msg) 486 .setPositiveButton(getActivity().getString(R.string.dlg_ok), mDisconnectListener) 487 .setNegativeButton(getActivity().getString(R.string.dlg_cancel), null) 488 .create(); 489 return dialog; 490 } else if (id == DIALOG_CANCEL_CONNECT) { 491 int stringId = R.string.wifi_p2p_cancel_connect_message; 492 String deviceName = TextUtils.isEmpty(mSelectedWifiPeer.device.deviceName) ? 493 mSelectedWifiPeer.device.deviceAddress : 494 mSelectedWifiPeer.device.deviceName; 495 496 AlertDialog dialog = new AlertDialog.Builder(getActivity()) 497 .setTitle(R.string.wifi_p2p_cancel_connect_title) 498 .setMessage(getActivity().getString(stringId, deviceName)) 499 .setPositiveButton(getActivity().getString(R.string.dlg_ok), mCancelConnectListener) 500 .setNegativeButton(getActivity().getString(R.string.dlg_cancel), null) 501 .create(); 502 return dialog; 503 } else if (id == DIALOG_RENAME) { 504 final LayoutInflater layoutInflater = LayoutInflater.from(getPrefContext()); 505 final View root = layoutInflater.inflate(R.layout.dialog_edittext, null /* root */); 506 mDeviceNameText = root.findViewById(R.id.edittext); 507 mDeviceNameText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(22)}); 508 if (mSavedDeviceName != null) { 509 mDeviceNameText.setText(mSavedDeviceName); 510 mDeviceNameText.setSelection(mSavedDeviceName.length()); 511 } else if (mThisDevice != null && !TextUtils.isEmpty(mThisDevice.deviceName)) { 512 mDeviceNameText.setText(mThisDevice.deviceName); 513 mDeviceNameText.setSelection(0, mThisDevice.deviceName.length()); 514 } 515 mSavedDeviceName = null; 516 AlertDialog dialog = new AlertDialog.Builder(getActivity()) 517 .setTitle(R.string.wifi_p2p_menu_rename) 518 .setView(root) 519 .setPositiveButton(getActivity().getString(R.string.dlg_ok), mRenameListener) 520 .setNegativeButton(getActivity().getString(R.string.dlg_cancel), null) 521 .create(); 522 return dialog; 523 } else if (id == DIALOG_DELETE_GROUP) { 524 int stringId = R.string.wifi_p2p_delete_group_message; 525 526 AlertDialog dialog = new AlertDialog.Builder(getActivity()) 527 .setMessage(getActivity().getString(stringId)) 528 .setPositiveButton(getActivity().getString(R.string.dlg_ok), mDeleteGroupListener) 529 .setNegativeButton(getActivity().getString(R.string.dlg_cancel), 530 mDeleteGroupListener).create(); 531 return dialog; 532 } 533 return null; 534 } 535 536 @Override getDialogMetricsCategory(int dialogId)537 public int getDialogMetricsCategory(int dialogId) { 538 switch (dialogId) { 539 case DIALOG_DISCONNECT: 540 return SettingsEnums.DIALOG_WIFI_P2P_DISCONNECT; 541 case DIALOG_CANCEL_CONNECT: 542 return SettingsEnums.DIALOG_WIFI_P2P_CANCEL_CONNECT; 543 case DIALOG_RENAME: 544 return SettingsEnums.DIALOG_WIFI_P2P_RENAME; 545 case DIALOG_DELETE_GROUP: 546 return SettingsEnums.DIALOG_WIFI_P2P_DELETE_GROUP; 547 } 548 return 0; 549 } 550 551 @Override onSaveInstanceState(Bundle outState)552 public void onSaveInstanceState(Bundle outState) { 553 if (mSelectedWifiPeer != null) { 554 outState.putParcelable(SAVE_DIALOG_PEER, mSelectedWifiPeer.device); 555 } 556 if (mDeviceNameText != null) { 557 outState.putString(SAVE_DEVICE_NAME, mDeviceNameText.getText().toString()); 558 } 559 if (mSelectedGroup != null) { 560 outState.putString(SAVE_SELECTED_GROUP, mSelectedGroup.getGroupName()); 561 } 562 } 563 handlePeersChanged()564 private void handlePeersChanged() { 565 mPeerCategoryController.removeAllChildren(); 566 567 mConnectedDevices = 0; 568 if (DBG) Log.d(TAG, "List of available peers"); 569 for (WifiP2pDevice peer: mPeers.getDeviceList()) { 570 if (DBG) Log.d(TAG, "-> " + peer); 571 mPeerCategoryController.addChild(new WifiP2pPeer(getPrefContext(), peer)); 572 if (peer.status == WifiP2pDevice.CONNECTED) mConnectedDevices++; 573 } 574 if (DBG) Log.d(TAG, " mConnectedDevices " + mConnectedDevices); 575 } 576 577 @Override onPersistentGroupInfoAvailable(WifiP2pGroupList groups)578 public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups) { 579 mPersistentCategoryController.removeAllChildren(); 580 581 for (WifiP2pGroup group: groups.getGroupList()) { 582 if (DBG) Log.d(TAG, " group " + group); 583 WifiP2pPersistentGroup wppg = new WifiP2pPersistentGroup(getPrefContext(), group); 584 mPersistentCategoryController.addChild(wppg); 585 if (wppg.getGroupName().equals(mSelectedGroupName)) { 586 if (DBG) Log.d(TAG, "Selecting group " + wppg.getGroupName()); 587 mSelectedGroup = wppg; 588 mSelectedGroupName = null; 589 } 590 } 591 if (mSelectedGroupName != null) { 592 // Looks like there's a dialog pending getting user confirmation to delete the 593 // selected group. When user hits OK on that dialog, we won't do anything; but we 594 // shouldn't be in this situation in first place, because these groups are persistent 595 // groups and they shouldn't just get deleted! 596 Log.w(TAG, " Selected group " + mSelectedGroupName + " disappered on next query "); 597 } 598 } 599 600 @Override onPeersAvailable(WifiP2pDeviceList peers)601 public void onPeersAvailable(WifiP2pDeviceList peers) { 602 if (DBG) Log.d(TAG, "Requested peers are available"); 603 mPeers = peers; 604 handlePeersChanged(); 605 } 606 607 @Override onDeviceInfoAvailable(WifiP2pDevice wifiP2pDevice)608 public void onDeviceInfoAvailable(WifiP2pDevice wifiP2pDevice) { 609 mThisDevice = wifiP2pDevice; 610 if (DBG) Log.d(TAG, "Update device info: " + mThisDevice); 611 mThisDevicePreferenceController.updateDeviceName(mThisDevice); 612 if (wifiP2pDevice.status == WifiP2pDevice.UNAVAILABLE 613 || wifiP2pDevice.status == WifiP2pDevice.FAILED) { 614 return; 615 } 616 onDeviceAvailable(); 617 } 618 onDeviceAvailable()619 private void onDeviceAvailable() { 620 if (mWifiP2pManager == null || sChannel == null) { 621 return; 622 } 623 mWifiP2pManager.requestNetworkInfo(sChannel, networkInfo -> { 624 if (sChannel == null) return; 625 mWifiP2pManager.requestConnectionInfo(sChannel, wifip2pinfo -> { 626 if (!mIsIgnoreInitConnectionInfoCallback) { 627 if (networkInfo.isConnected()) { 628 if (DBG) { 629 Log.d(TAG, "Connected"); 630 } 631 } else if (!mLastGroupFormed) { 632 // Find peers when p2p doesn't connected. 633 startSearch(); 634 } 635 mLastGroupFormed = wifip2pinfo.groupFormed; 636 } 637 }); 638 }); 639 } 640 handleP2pStateChanged()641 private void handleP2pStateChanged() { 642 mThisDevicePreferenceController.setEnabled(mWifiP2pEnabled); 643 mPersistentCategoryController.setEnabled(mWifiP2pEnabled); 644 mPeerCategoryController.setEnabled(mWifiP2pEnabled); 645 if (mWifiP2pEnabled) { 646 startSearch(); 647 } 648 updateSearchMenu(mWifiP2pEnabled); 649 } 650 updateSearchMenu(boolean searching)651 private void updateSearchMenu(boolean searching) { 652 mWifiP2pSearching = searching; 653 Activity activity = getActivity(); 654 if (activity != null) activity.invalidateOptionsMenu(); 655 } 656 startSearch()657 private void startSearch() { 658 if (mWifiP2pManager != null && sChannel != null && !mWifiP2pSearching) { 659 mWifiP2pManager.discoverPeers(sChannel, new WifiP2pManager.ActionListener() { 660 public void onSuccess() { 661 } 662 public void onFailure(int reason) { 663 if (DBG) Log.d(TAG, " discover fail " + reason); 664 } 665 }); 666 } 667 } 668 initChannel()669 private boolean initChannel() { 670 if (sChannel != null) { 671 return true; 672 } 673 if (mWifiP2pManager != null) { 674 sChannel = mWifiP2pManager.initialize(getActivity().getApplicationContext(), 675 getActivity().getMainLooper(), null); 676 } 677 if (sChannel == null) { 678 Log.e(TAG, "Failed to set up connection with wifi p2p service"); 679 return false; 680 } 681 return true; 682 } 683 } 684