1 /* 2 * Copyright (C) 2022 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.tv.settings.system.development; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.database.ContentObserver; 24 import android.debug.AdbManager; 25 import android.debug.FingerprintAndPairDevice; 26 import android.debug.IAdbManager; 27 import android.debug.PairDevice; 28 import android.graphics.drawable.Drawable; 29 import android.net.ConnectivityManager; 30 import android.net.LinkAddress; 31 import android.net.LinkProperties; 32 import android.net.Network; 33 import android.net.NetworkCapabilities; 34 import android.net.NetworkInfo; 35 import android.net.NetworkRequest; 36 import android.net.Uri; 37 import android.os.Build; 38 import android.os.Bundle; 39 import android.os.Handler; 40 import android.os.Looper; 41 import android.os.RemoteException; 42 import android.os.ServiceManager; 43 import android.provider.Settings; 44 import android.util.Log; 45 import android.view.LayoutInflater; 46 import android.view.View; 47 import android.view.ViewGroup; 48 import android.widget.ImageView; 49 import android.widget.TextView; 50 51 import androidx.annotation.Keep; 52 import androidx.leanback.app.GuidedStepSupportFragment; 53 import androidx.leanback.widget.GuidanceStylist; 54 import androidx.leanback.widget.GuidedAction; 55 import androidx.leanback.widget.GuidedActionsStylist; 56 import androidx.preference.Preference; 57 import androidx.preference.PreferenceCategory; 58 59 import com.android.tv.settings.R; 60 import com.android.tv.settings.RadioPreference; 61 import com.android.tv.settings.SettingsPreferenceFragment; 62 63 import java.net.Inet4Address; 64 import java.net.InetAddress; 65 import java.util.HashMap; 66 import java.util.Iterator; 67 import java.util.List; 68 import java.util.Map; 69 70 /** 71 * Fragment shown when clicking in the "Wireless Debugging" preference in 72 * the developer options. 73 */ 74 @Keep 75 public class WirelessDebuggingFragment extends SettingsPreferenceFragment { 76 private static final String TAG = "WirelessDebuggingFrag"; 77 78 private static final String PREF_KEY_ADB_WIRELESS_SELECTION_OPTION = 79 "adb_wireless_selection_option"; 80 private static final String PREF_KEY_ADB_WIRELESS_SELECTION_DISABLE = 81 "adb_wireless_selection_disable"; 82 private static final String PREF_KEY_ADB_WIRELESS_SELECTION_ENABLE = 83 "adb_wireless_selection_enable"; 84 private static final String PREF_KEY_ADB_CODE_PAIRING = "adb_pair_method_code_pref"; 85 private static final String PREF_KEY_ADB_DEVICE_NAME = "adb_device_name_pref"; 86 private static final String PREF_KEY_ADB_IP_ADDR = "adb_ip_addr_pref"; 87 private static final String PREF_KEY_PAIRED_DEVICES_CATEGORY = "adb_paired_devices_category"; 88 89 private IAdbManager mAdbManager; 90 private ContentObserver mToggleContentObserver; 91 private ConnectivityManager mConnectivityManager; 92 private final Handler mHandler = new Handler(Looper.getMainLooper()); 93 private IntentFilter mIntentFilter; 94 95 private PreferenceCategory mAdbWirelessSelectionOption; 96 private RadioPreference mAdbWirelessSelectionDisable; 97 private RadioPreference mAdbWirelessSelectionEnable; 98 private Preference mCodePairingPreference; 99 private Preference mDeviceNamePreference; 100 private Preference mIpAddrPreference; 101 private PreferenceCategory mPairedDevicesCategory; 102 103 private final WifiNetworkCallback mWifiNetworkCallback = new WifiNetworkCallback(); 104 105 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 106 @Override 107 public void onReceive(Context context, Intent intent) { 108 String action = intent.getAction(); 109 if (AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION.equals(action)) { 110 Map<String, PairDevice> newPairedDevicesList = 111 (HashMap<String, PairDevice>) intent.getSerializableExtra( 112 AdbManager.WIRELESS_DEVICES_EXTRA); 113 updatePairedDevicePreferences(newPairedDevicesList); 114 } else if (AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION.equals(action)) { 115 int status = intent.getIntExtra(AdbManager.WIRELESS_STATUS_EXTRA, 116 AdbManager.WIRELESS_STATUS_DISCONNECTED); 117 if (status == AdbManager.WIRELESS_STATUS_CONNECTED 118 || status == AdbManager.WIRELESS_STATUS_DISCONNECTED) { 119 updateAdbIpAddressPreference(); 120 } 121 } 122 } 123 }; 124 125 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)126 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 127 setPreferencesFromResource(getPreferenceScreenResId(), null); 128 129 addPreferences(); 130 showBlankPreferences(); 131 132 mAdbManager = IAdbManager.Stub.asInterface(ServiceManager.getService( 133 Context.ADB_SERVICE)); 134 mToggleContentObserver = new ContentObserver(new Handler(Looper.myLooper())) { 135 @Override 136 public void onChange(boolean selfChange, Uri uri) { 137 updatePreferenceState(); 138 } 139 }; 140 141 mConnectivityManager = getContext().getSystemService(ConnectivityManager.class); 142 143 mIntentFilter = new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION); 144 mIntentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION); 145 146 initAdbWirelessSelectionOptionPreference(); 147 } 148 149 @Override onResume()150 public void onResume() { 151 super.onResume(); 152 getContext().getContentResolver().registerContentObserver( 153 Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED), 154 false, 155 mToggleContentObserver); 156 mConnectivityManager.registerNetworkCallback( 157 new NetworkRequest.Builder() 158 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 159 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) 160 .build(), 161 mWifiNetworkCallback); 162 getActivity().registerReceiver(mReceiver, mIntentFilter); 163 } 164 165 @Override onPause()166 public void onPause() { 167 super.onPause(); 168 getContext().getContentResolver().unregisterContentObserver(mToggleContentObserver); 169 mConnectivityManager.unregisterNetworkCallback(mWifiNetworkCallback); 170 getActivity().unregisterReceiver(mReceiver); 171 } 172 getPreferenceScreenResId()173 private int getPreferenceScreenResId() { 174 return R.xml.adb_wireless_settings; 175 } 176 addPreferences()177 private void addPreferences() { 178 mAdbWirelessSelectionOption = findPreference(PREF_KEY_ADB_WIRELESS_SELECTION_OPTION); 179 mAdbWirelessSelectionDisable = findPreference(PREF_KEY_ADB_WIRELESS_SELECTION_DISABLE); 180 mAdbWirelessSelectionEnable = findPreference(PREF_KEY_ADB_WIRELESS_SELECTION_ENABLE); 181 mCodePairingPreference = findPreference(PREF_KEY_ADB_CODE_PAIRING); 182 mDeviceNamePreference = findPreference(PREF_KEY_ADB_DEVICE_NAME); 183 mIpAddrPreference = findPreference(PREF_KEY_ADB_IP_ADDR); 184 mPairedDevicesCategory = findPreference(PREF_KEY_PAIRED_DEVICES_CATEGORY); 185 } 186 187 @Override onPreferenceTreeClick(Preference preference)188 public boolean onPreferenceTreeClick(Preference preference) { 189 switch (preference.getKey()) { 190 case PREF_KEY_ADB_WIRELESS_SELECTION_ENABLE: 191 setWirelessDebuggingRadioButtonEnabled(true); 192 Settings.Global.putInt(getContext().getContentResolver(), 193 Settings.Global.ADB_WIFI_ENABLED, 194 1); 195 break; 196 case PREF_KEY_ADB_WIRELESS_SELECTION_DISABLE: 197 setWirelessDebuggingRadioButtonEnabled(false); 198 Settings.Global.putInt(getContext().getContentResolver(), 199 Settings.Global.ADB_WIFI_ENABLED, 200 0); 201 break; 202 } 203 return super.onPreferenceTreeClick(preference); 204 } 205 initAdbWirelessSelectionOptionPreference()206 private void initAdbWirelessSelectionOptionPreference() { 207 boolean enabled = Settings.Global.getInt(getContext().getContentResolver(), 208 Settings.Global.ADB_WIFI_ENABLED, 1) != 0; 209 setWirelessDebuggingRadioButtonEnabled(enabled); 210 } 211 updatePreferenceState()212 private void updatePreferenceState() { 213 if (!isNetworkConnected()) { 214 showBlankPreferences(); 215 } else { 216 boolean enabled = Settings.Global.getInt(getContext().getContentResolver(), 217 Settings.Global.ADB_WIFI_ENABLED, 1) != 0; 218 if (enabled) { 219 showDebuggingPreferences(); 220 try { 221 FingerprintAndPairDevice[] newList = mAdbManager.getPairedDevices(); 222 Map<String, PairDevice> newMap = new HashMap<>(); 223 for (FingerprintAndPairDevice pair : newList) { 224 newMap.put(pair.keyFingerprint, pair.device); 225 } 226 updatePairedDevicePreferences(newMap); 227 int connectionPort = mAdbManager.getAdbWirelessPort(); 228 if (connectionPort > 0) { 229 Log.i(TAG, "onEnabled(): connect_port=" + connectionPort); 230 } 231 } catch (RemoteException e) { 232 Log.e(TAG, "Unable to request the paired list for Adb wireless"); 233 } 234 updateAdbIpAddressPreference(); 235 } else { 236 showOffMessage(); 237 } 238 } 239 } 240 showBlankPreferences()241 private void showBlankPreferences() { 242 if (mAdbWirelessSelectionOption != null) { 243 mAdbWirelessSelectionOption.setVisible(false); 244 } 245 if (mCodePairingPreference != null) { 246 mCodePairingPreference.setVisible(false); 247 } 248 if (mDeviceNamePreference != null) { 249 mDeviceNamePreference.setVisible(false); 250 } 251 if (mIpAddrPreference != null) { 252 mIpAddrPreference.setVisible(false); 253 } 254 if (mPairedDevicesCategory != null) { 255 mPairedDevicesCategory.setVisible(false); 256 } 257 } 258 showOffMessage()259 private void showOffMessage() { 260 setWirelessDebuggingRadioButtonEnabled(false); 261 if (mAdbWirelessSelectionOption != null) { 262 mAdbWirelessSelectionOption.setVisible(true); 263 } 264 if (mCodePairingPreference != null) { 265 mCodePairingPreference.setVisible(false); 266 } 267 if (mDeviceNamePreference != null) { 268 mDeviceNamePreference.setVisible(false); 269 } 270 if (mIpAddrPreference != null) { 271 mIpAddrPreference.setVisible(false); 272 } 273 if (mPairedDevicesCategory != null) { 274 mPairedDevicesCategory.setVisible(false); 275 } 276 } 277 showDebuggingPreferences()278 private void showDebuggingPreferences() { 279 setWirelessDebuggingRadioButtonEnabled(true); 280 if (mAdbWirelessSelectionOption != null) { 281 mAdbWirelessSelectionOption.setVisible(true); 282 } 283 if (mCodePairingPreference != null) { 284 mCodePairingPreference.setVisible(true); 285 } 286 if (mDeviceNamePreference != null) { 287 mDeviceNamePreference.setSummary(getDeviceName()); 288 mDeviceNamePreference.setVisible(true); 289 } 290 if (mIpAddrPreference != null) { 291 mIpAddrPreference.setVisible(true); 292 } 293 if (mPairedDevicesCategory != null) { 294 mPairedDevicesCategory.setVisible(true); 295 } 296 } 297 setWirelessDebuggingRadioButtonEnabled(boolean enabled)298 private void setWirelessDebuggingRadioButtonEnabled(boolean enabled) { 299 if (mAdbWirelessSelectionEnable != null) { 300 mAdbWirelessSelectionEnable.setChecked(enabled); 301 } 302 if (mAdbWirelessSelectionDisable != null) { 303 mAdbWirelessSelectionDisable.setChecked(!enabled); 304 } 305 } 306 updatePairedDevicePreferences(Map<String, PairDevice> newList)307 private void updatePairedDevicePreferences(Map<String, PairDevice> newList) { 308 if (newList == null) { 309 mPairedDevicesCategory.removeAll(); 310 return; 311 } 312 for (int i = 0; i < mPairedDevicesCategory.getPreferenceCount(); i++) { 313 AdbPairedDevicePreference p = 314 (AdbPairedDevicePreference) mPairedDevicesCategory.getPreference(i); 315 // Remove any devices no longer on the newList 316 if (!newList.containsKey(p.getKey())) { 317 mPairedDevicesCategory.removePreference(p); 318 } else { 319 // It is in the newList. Just update the PairDevice value 320 p.setPairedDevice(newList.get(p.getKey())); 321 p.refresh(); 322 } 323 } 324 // Add new devices if any. 325 for (Map.Entry<String, PairDevice> entry : 326 newList.entrySet()) { 327 if (mPairedDevicesCategory.findPreference(entry.getKey()) == null) { 328 AdbPairedDevicePreference p = 329 new AdbPairedDevicePreference(entry.getValue(), 330 mPairedDevicesCategory.getContext()); 331 p.setKey(entry.getKey()); 332 mPairedDevicesCategory.addPreference(p); 333 } 334 } 335 } 336 updateAdbIpAddressPreference()337 private void updateAdbIpAddressPreference() { 338 if (mIpAddrPreference != null) { 339 String ipAddress = getIpAddressPort(); 340 mIpAddrPreference.setSummary(ipAddress); 341 } 342 } 343 getDeviceName()344 private String getDeviceName() { 345 String deviceName = Settings.Global.getString(getContext().getContentResolver(), 346 Settings.Global.DEVICE_NAME); 347 if (deviceName == null) { 348 deviceName = Build.MODEL; 349 } 350 return deviceName; 351 } 352 isNetworkConnected()353 private boolean isNetworkConnected() { 354 NetworkInfo activeNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); 355 return activeNetworkInfo != null && activeNetworkInfo.isConnected(); 356 } 357 getIpAddressPort()358 private String getIpAddressPort() { 359 String ipAddress = getWifiIpv4Address(); 360 if (ipAddress != null) { 361 int port = getAdbWirelessPort(); 362 if (port <= 0) { 363 return getString(R.string.status_unavailable); 364 } else { 365 ipAddress += ":" + port; 366 } 367 return ipAddress; 368 } else { 369 return getString(R.string.status_unavailable); 370 } 371 } 372 getAdbWirelessPort()373 private int getAdbWirelessPort() { 374 try { 375 return mAdbManager.getAdbWirelessPort(); 376 } catch (RemoteException e) { 377 Log.e(TAG, "Unable to get the adb wifi port"); 378 } 379 return 0; 380 } 381 getWifiIpv4Address()382 private String getWifiIpv4Address() { 383 LinkProperties prop = mConnectivityManager.getLinkProperties( 384 mConnectivityManager.getActiveNetwork()); 385 return formatIpAddresses(prop); 386 } 387 formatIpAddresses(LinkProperties prop)388 private static String formatIpAddresses(LinkProperties prop) { 389 if (prop == null) { 390 return null; 391 } 392 393 Iterator<LinkAddress> iter = prop.getAllLinkAddresses().iterator(); 394 if (!iter.hasNext()) { 395 return null; 396 } 397 398 StringBuilder addresses = new StringBuilder(); 399 while (iter.hasNext()) { 400 InetAddress addr = iter.next().getAddress(); 401 if (addr instanceof Inet4Address) { 402 addresses.append(addr.getHostAddress()); 403 break; 404 } 405 } 406 return addresses.toString(); 407 } 408 409 private class WifiNetworkCallback extends ConnectivityManager.NetworkCallback { 410 @Override onAvailable(Network network)411 public void onAvailable(Network network) { 412 super.onAvailable(network); 413 mHandler.post(() -> updatePreferenceState()); 414 } 415 416 @Override onLost(Network network)417 public void onLost(Network network) { 418 super.onLost(network); 419 mHandler.post(() -> updatePreferenceState()); 420 } 421 } 422 423 /** 424 * Fragment for showing the pairing code and IP address & port to pair the device 425 */ 426 @Keep 427 public static class PairingCodeFragment extends GuidedStepSupportFragment { 428 private String mPairingCode; 429 private String mIpAddressPort; 430 431 private ImageView mIconView; 432 private TextView mPairingCodeTitleTextView; 433 private TextView mPairingCodeTextView; 434 private TextView mIpAddressPortTitleTextView; 435 private TextView mIpAddressPortTextView; 436 437 private IAdbManager mAdbManager; 438 private IntentFilter mIntentFilter; 439 private ConnectivityManager mConnectivityManager; 440 441 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 442 @Override 443 public void onReceive(Context context, Intent intent) { 444 String action = intent.getAction(); 445 if (AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION.equals(action)) { 446 Integer res = intent.getIntExtra( 447 AdbManager.WIRELESS_STATUS_EXTRA, 448 AdbManager.WIRELESS_STATUS_FAIL); 449 450 if (res.equals(AdbManager.WIRELESS_STATUS_PAIRING_CODE)) { 451 String pairingCode = intent.getStringExtra( 452 AdbManager.WIRELESS_PAIRING_CODE_EXTRA); 453 Log.d(TAG, "Received 6 digit pairing code: " + pairingCode); 454 mPairingCode = pairingCode; 455 refresh(mPairingCode, mIpAddressPort); 456 } else if (res.equals(AdbManager.WIRELESS_STATUS_CONNECTED)) { 457 int port = intent.getIntExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, 0); 458 Log.i(TAG, "Got pairing code port=" + port); 459 String ipAddr = getWifiIpv4Address() + ":" + port; 460 mIpAddressPort = ipAddr; 461 refresh(mPairingCode, mIpAddressPort); 462 } 463 } 464 } 465 }; 466 467 @Override onCreate(Bundle savedInstanceState)468 public void onCreate(Bundle savedInstanceState) { 469 super.onCreate(savedInstanceState); 470 mConnectivityManager = getContext().getSystemService(ConnectivityManager.class); 471 mIntentFilter = new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); 472 mAdbManager = IAdbManager.Stub.asInterface(ServiceManager.getService( 473 Context.ADB_SERVICE)); 474 } 475 476 @Override onResume()477 public void onResume() { 478 super.onResume(); 479 getActivity().registerReceiver(mReceiver, mIntentFilter); 480 try { 481 mAdbManager.enablePairingByPairingCode(); 482 } catch (RemoteException e) { 483 Log.e(TAG, "Unable to enable pairing"); 484 } 485 } 486 487 @Override onPause()488 public void onPause() { 489 super.onPause(); 490 getActivity().unregisterReceiver(mReceiver); 491 try { 492 mAdbManager.disablePairing(); 493 } catch (RemoteException e) { 494 Log.e(TAG, "Unable to disable pairing"); 495 } 496 } 497 498 @Override onCreateGuidance(Bundle savedInstanceState)499 public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) { 500 Drawable networkIcon; 501 if (isWifiNetwork()) { 502 networkIcon = getContext().getDrawable(R.drawable.ic_adb_wifi_132dp); 503 } else { 504 networkIcon = getContext().getDrawable(R.drawable.ic_adb_ethernet_132dp); 505 } 506 return new GuidanceStylist.Guidance( 507 getString(R.string.adb_pairing_device_dialog_title), 508 null, 509 null, 510 networkIcon 511 ); 512 } 513 514 @Override onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState)515 public void onCreateActions(List<GuidedAction> actions, 516 Bundle savedInstanceState) { 517 actions.add(new GuidedAction.Builder(getContext()) 518 .build()); 519 } 520 521 @Override onCreateGuidanceStylist()522 public GuidanceStylist onCreateGuidanceStylist() { 523 return new GuidanceStylist() { 524 @Override 525 public View onCreateView(LayoutInflater inflater, ViewGroup container, 526 Guidance guidance) { 527 View view = super.onCreateView(inflater, container, guidance); 528 mIconView = getIconView(); 529 return view; 530 } 531 }; 532 } 533 534 @Override onCreateActionsStylist()535 public GuidedActionsStylist onCreateActionsStylist() { 536 return new GuidedActionsStylist() { 537 @Override 538 public int onProvideItemLayoutId() { 539 return R.layout.pairing_code_guided_action; 540 } 541 542 @Override 543 public ViewHolder onCreateViewHolder(ViewGroup parent) { 544 ViewHolder viewHolder = super.onCreateViewHolder(parent); 545 mPairingCodeTitleTextView = 546 viewHolder.itemView.findViewById(R.id.pairing_code_title); 547 mPairingCodeTextView = 548 viewHolder.itemView.findViewById(R.id.pairing_code); 549 mIpAddressPortTitleTextView = 550 viewHolder.itemView.findViewById(R.id.ip_address_port_title); 551 mIpAddressPortTextView = 552 viewHolder.itemView.findViewById(R.id.ip_address_port); 553 554 if (mPairingCodeTitleTextView != null) { 555 mPairingCodeTitleTextView.setText(isWifiNetwork() 556 ? R.string.adb_pairing_device_dialog_pairing_code_label 557 : R.string.adb_pairing_device_dialog_ethernet_pairing_code_label); 558 } 559 if (mPairingCodeTextView != null) { 560 mPairingCodeTextView.setText(mPairingCode); 561 } 562 if (mIpAddressPortTitleTextView != null) { 563 mIpAddressPortTitleTextView.setText( 564 R.string.adb_wireless_ip_addr_preference_title); 565 } 566 if (mIpAddressPortTextView != null) { 567 mIpAddressPortTextView.setText(mIpAddressPort); 568 } 569 570 return viewHolder; 571 } 572 }; 573 } 574 575 private void refresh(String pairingCode, String ipAddressPort) { 576 mPairingCode = pairingCode; 577 mIpAddressPort = ipAddressPort; 578 boolean isWifiNetwork = isWifiNetwork(); 579 580 if (mIconView != null) { 581 mIconView.setImageDrawable(isWifiNetwork 582 ? getContext().getDrawable(R.drawable.ic_adb_wifi_132dp) 583 : getContext().getDrawable(R.drawable.ic_adb_ethernet_132dp)); 584 } 585 586 if (mPairingCodeTitleTextView != null) { 587 mPairingCodeTitleTextView.setText(isWifiNetwork 588 ? R.string.adb_pairing_device_dialog_pairing_code_label 589 : R.string.adb_pairing_device_dialog_ethernet_pairing_code_label); 590 } 591 if (mPairingCodeTextView != null) { 592 mPairingCodeTextView.setText(mPairingCode); 593 } 594 if (mIpAddressPortTextView != null) { 595 mIpAddressPortTextView.setText(mIpAddressPort); 596 } 597 } 598 599 private boolean isWifiNetwork() { 600 NetworkInfo activeNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); 601 return activeNetworkInfo != null && activeNetworkInfo.isConnected() 602 && ConnectivityManager.TYPE_ETHERNET != activeNetworkInfo.getType(); 603 } 604 605 private String getWifiIpv4Address() { 606 LinkProperties prop = mConnectivityManager.getLinkProperties( 607 mConnectivityManager.getActiveNetwork()); 608 return formatIpAddresses(prop); 609 } 610 611 private static String formatIpAddresses(LinkProperties prop) { 612 if (prop == null) { 613 return null; 614 } 615 616 Iterator<LinkAddress> iter = prop.getAllLinkAddresses().iterator(); 617 if (!iter.hasNext()) { 618 return null; 619 } 620 621 StringBuilder addresses = new StringBuilder(); 622 while (iter.hasNext()) { 623 InetAddress addr = iter.next().getAddress(); 624 if (addr instanceof Inet4Address) { 625 addresses.append(addr.getHostAddress()); 626 break; 627 } 628 } 629 return addresses.toString(); 630 } 631 } 632 } 633