summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-10-16 20:22:48 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-10-16 20:22:48 +0000
commitef00e525b188a1e2ebb5cc199471be11f18d0d10 (patch)
tree889c48fd038beb52cb02bf3509d92e5c5f53971b
parent5bcedf54c7b09454fbd2150936883f76d0838c94 (diff)
parent4d2f36d50f6a96c23a98c11617782fde04d4a5c2 (diff)
downloadwifi-ef00e525b188a1e2ebb5cc199471be11f18d0d10.tar.gz
Snap for 10957012 from 4d2f36d50f6a96c23a98c11617782fde04d4a5c2 to simpleperf-release
Change-Id: Ibcd504f076f078fe9e6bdbce7f1d2f3b4d23330c
-rw-r--r--libs/WifiTrackerLib/res/values-af/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-am/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ar/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-as/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-az/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-be/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-bg/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-bn/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-bs/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ca/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-cs/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-da/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-de/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-el/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-en-rAU/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-en-rCA/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-en-rGB/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-en-rIN/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-en-rXC/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-es-rUS/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-es/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-et/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-eu/strings.xml11
-rw-r--r--libs/WifiTrackerLib/res/values-fa/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-fi/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-fr-rCA/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-fr/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-gl/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-gu/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-hi/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-hr/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-hu/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-hy/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-in/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-is/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-it/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-iw/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ja/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ka/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-kk/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-km/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-kn/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ko/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ky/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-lo/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-lt/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-lv/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-mk/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ml/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-mn/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-mr/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ms/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-my/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-nb/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ne/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-nl/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-or/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-pa/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-pl/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-pt-rBR/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-pt-rPT/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-pt/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ro/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ru/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-si/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-sk/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-sl/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-sq/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-sr/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-sv/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-sw/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ta/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-te/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-th/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-tl/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-tr/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-uk/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-ur/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-uz/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-vi/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-zh-rCN/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-zh-rHK/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-zh-rTW/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values-zu/strings.xml9
-rw-r--r--libs/WifiTrackerLib/res/values/strings.xml23
-rw-r--r--libs/WifiTrackerLib/sdk_src/src/com/android/wifitrackerlib/NonSdkApiWrapper.java34
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java549
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/HotspotNetworkDetailsTracker.java161
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/HotspotNetworkEntry.java459
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/KnownNetworkEntry.java143
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/MergedCarrierEntry.java4
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java67
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java30
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/NonSdkApiWrapper.java32
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java4
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java31
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java45
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java229
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/ScanResultUpdater.java4
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java51
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java98
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java151
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java315
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java610
-rw-r--r--libs/WifiTrackerLib/tests/Android.bp2
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/HotspotNetworkEntryTest.java371
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/KnownNetworkEntryTest.java135
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/MergedCarrierEntryTest.java16
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NetworkDetailsTrackerTest.java27
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NonSdkApiWrapperTest.java10
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java166
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/SavedNetworkTrackerTest.java241
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardNetworkDetailsTrackerTest.java69
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java371
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/TestUtils.java7
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java142
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java1111
-rw-r--r--libwifi_hal/Android.bp1
119 files changed, 5360 insertions, 1116 deletions
diff --git a/libs/WifiTrackerLib/res/values-af/strings.xml b/libs/WifiTrackerLib/res/values-af/strings.xml
index 229ceeea9..2d42d17da 100644
--- a/libs/WifiTrackerLib/res/values-af/strings.xml
+++ b/libs/WifiTrackerLib/res/values-af/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Gekoppel aan toestel. Kan nie internet verskaf nie."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lae gehalte"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Word nie deur jou organisasie toegelaat nie"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> van <xliff:g id="MODEL_NAME">%2$s</xliff:g> af"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> van <xliff:g id="DEVICE_NAME">%2$s</xliff:g> af"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Koppel tans …"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Beskikbaar vanaf <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Onbekend"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-am/strings.xml b/libs/WifiTrackerLib/res/values-am/strings.xml
index 7d075f357..62b685778 100644
--- a/libs/WifiTrackerLib/res/values-am/strings.xml
+++ b/libs/WifiTrackerLib/res/values-am/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ከመሣሪያው ጋር ተገናኝቷል። በይነመረብ ማቅረብ አልተቻለም።"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"አነስተኛ ጥራት"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"በእርስዎ ድርጅት አልተፈቀደም"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ከ<xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ከ<xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"በማገናኘት ላይ…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"ከ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ጀምሮ የሚገኝ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"ያልታወቀ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 ጊኸ"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 ጊኸ"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 ጊኸ"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"፣"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ar/strings.xml b/libs/WifiTrackerLib/res/values-ar/strings.xml
index 4a556f321..298ecfe2a 100644
--- a/libs/WifiTrackerLib/res/values-ar/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ar/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"الشبكة متصلة بالجهاز. يتعذّر توفير اتصال بالإنترنت."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"جودة منخفضة"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"لا تسمح بها مؤسستك"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"\"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\" من \"<xliff:g id="MODEL_NAME">%2$s</xliff:g>\""</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"\"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\" من \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\""</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"جارٍ الاتصال…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"تتوفّر من \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"‏شبكة Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"‏معيار WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"‏شبكة Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"غير معروف"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"٢٫٤ غيغاهرتز"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"٥ غيغاهرتز"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"٤ غيغاهرتز"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"،"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-as/strings.xml b/libs/WifiTrackerLib/res/values-as/strings.xml
index 6362f5655..6ec57207b 100644
--- a/libs/WifiTrackerLib/res/values-as/strings.xml
+++ b/libs/WifiTrackerLib/res/values-as/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ডিভাইচৰ সৈতে সংযোগ কৰা হৈছে। ইণ্টাৰনেট সংযোগ প্ৰদান কৰিব নোৱাৰি।"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"নিম্ন মানৰ"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"আপোনাৰ প্ৰতিষ্ঠানে অনুমতি নিদিয়ে"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g>ৰ পৰা <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>ৰ পৰা <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"সংযোগ কৰি থকা হৈছে…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ পৰা উপলব্ধ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"ৱাই-ফাই ৬"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"ৱাই-ফাই ৭"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"অজ্ঞাত"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"২.৪ গিগাহাৰ্টজ"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"৫ গিগাহাৰ্টজ"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"৬ গিগাহাৰ্টজ"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-az/strings.xml b/libs/WifiTrackerLib/res/values-az/strings.xml
index 7d0327baa..c1d7049a4 100644
--- a/libs/WifiTrackerLib/res/values-az/strings.xml
+++ b/libs/WifiTrackerLib/res/values-az/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Cihaza qoşulub. İnternet təmin etmək olmur."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Aşağı keyfiyyət"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Təşkilatınız icazə vermir"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> tərəfindən <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> tərəfindən <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Qoşulur…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazından əlçatandır"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Müəssisə"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Naməlum"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml b/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml
index 66f27a753..df09f8361 100644
--- a/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml
+++ b/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Uređaj je povezan. Pružanje interneta nije uspelo."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Loš kvalitet"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Ne dozvoljava vaša organizacija"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> – <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> – <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Povezuje se…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Dostupno sa uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"WiFi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"WiFi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Nepoznato"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-be/strings.xml b/libs/WifiTrackerLib/res/values-be/strings.xml
index f1e7ff61b..7e3137c8d 100644
--- a/libs/WifiTrackerLib/res/values-be/strings.xml
+++ b/libs/WifiTrackerLib/res/values-be/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Падключана да прылады. Не ўдалося падключыцца да інтэрнэту."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Нізкая якасць"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Забаронена ў вашай арганізацыі"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ад <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ад прылады <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Падключэнне…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Даступна тут: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Невядома"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 ГГц"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-bg/strings.xml b/libs/WifiTrackerLib/res/values-bg/strings.xml
index 563f99ea6..239e7daa4 100644
--- a/libs/WifiTrackerLib/res/values-bg/strings.xml
+++ b/libs/WifiTrackerLib/res/values-bg/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Установена е връзка с устройство. Няма интернет."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ниско качество"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Не се разрешава от организацията ви"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> от <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> от <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Свързва се…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Налице от <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Неизвестно"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-bn/strings.xml b/libs/WifiTrackerLib/res/values-bn/strings.xml
index 1b8f4735d..39cc301c1 100644
--- a/libs/WifiTrackerLib/res/values-bn/strings.xml
+++ b/libs/WifiTrackerLib/res/values-bn/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ডিভাইসের সাথে কানেক্ট করা। ইন্টারনেট পরিষেবা প্রদান করা যাচ্ছে না।"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"খারাপ কোয়ালিটি"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"আপনার প্রতিষ্ঠানের অননুমোদিত নেটওয়ার্ক"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> থেকে <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> থেকে <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"কানেক্ট করা হচ্ছে…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> থেকে উপলভ্য"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"ওয়াই-ফাই ৬"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"৬০ GHz ওয়াই-ফাই"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"ওয়াই-ফাই ৭"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"অজানা"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"২.৪ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"৫ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"৬ GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-bs/strings.xml b/libs/WifiTrackerLib/res/values-bs/strings.xml
index ce64f6ea0..c26b7c7fd 100644
--- a/libs/WifiTrackerLib/res/values-bs/strings.xml
+++ b/libs/WifiTrackerLib/res/values-bs/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Povezano s uređajem. Nije moguće pružiti internetsku vezu."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nizak kvalitet"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Ne dozvoljava vaša organizacija"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> s uređaja <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> s uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Povezivanje…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Dostupno je s uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"WiFi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"WiFi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Nepoznato"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ca/strings.xml b/libs/WifiTrackerLib/res/values-ca/strings.xml
index 91d960aa3..5d1002fd3 100644
--- a/libs/WifiTrackerLib/res/values-ca/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ca/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Connectat al dispositiu. Sense accés a Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Qualitat baixa"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"No permesa per la teva organització"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"S\'està connectant…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponible des de: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Desconeguda"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-cs/strings.xml b/libs/WifiTrackerLib/res/values-cs/strings.xml
index 4b2c95e74..ed574bb8a 100644
--- a/libs/WifiTrackerLib/res/values-cs/strings.xml
+++ b/libs/WifiTrackerLib/res/values-cs/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Připojeno k zařízení. Internet není k dispozici."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nízká kvalita"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Není povoleno vaší organizací"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ze zařízení <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ze zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Připojování…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"K dispozici ze zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Neznámé"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-da/strings.xml b/libs/WifiTrackerLib/res/values-da/strings.xml
index 4622b02f9..daf732acc 100644
--- a/libs/WifiTrackerLib/res/values-da/strings.xml
+++ b/libs/WifiTrackerLib/res/values-da/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Forbundet til enheden. Der er ikke noget internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Dårlig kvalitet"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Tillades ikke af din organisation"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> fra <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> fra <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Opretter forbindelse…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Tilgængelig fra <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Ukendt"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-de/strings.xml b/libs/WifiTrackerLib/res/values-de/strings.xml
index 59eeb81f7..f5ad11098 100644
--- a/libs/WifiTrackerLib/res/values-de/strings.xml
+++ b/libs/WifiTrackerLib/res/values-de/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Mit Gerät verbunden. Internetverbindung nicht möglich."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niedrige Qualität"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Von deiner Organisation nicht zugelassen"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> von <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> von <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Wird verbunden…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Verfügbar auf <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2 EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2 Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3 EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Unbekannt"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-el/strings.xml b/libs/WifiTrackerLib/res/values-el/strings.xml
index 93dd14f8d..61eaa40b2 100644
--- a/libs/WifiTrackerLib/res/values-el/strings.xml
+++ b/libs/WifiTrackerLib/res/values-el/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Συνδέθηκε στη συσκευή. Δεν είναι δυνατή η παροχή διαδικτύου."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Χαμηλή ποιότητα"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Δεν επιτρέπεται από τον οργανισμό σας"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> από <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> από <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Σύνδεση…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Διαθέσιμο από <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Εταιρικό"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Άγνωστο"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-en-rAU/strings.xml b/libs/WifiTrackerLib/res/values-en-rAU/strings.xml
index 2a128180b..9761f9084 100644
--- a/libs/WifiTrackerLib/res/values-en-rAU/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rAU/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Connected to device. Can\'t provide Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Not allowed by your organisation"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> from <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> from <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Connecting…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Available from <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Unknown"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-en-rCA/strings.xml b/libs/WifiTrackerLib/res/values-en-rCA/strings.xml
index 594583306..fefc6f0c7 100644
--- a/libs/WifiTrackerLib/res/values-en-rCA/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rCA/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Connected to device. Can\'t provide internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Not allowed by your organization"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> from <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> from <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Connecting…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Available from <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Unknown"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-en-rGB/strings.xml b/libs/WifiTrackerLib/res/values-en-rGB/strings.xml
index 2a128180b..9761f9084 100644
--- a/libs/WifiTrackerLib/res/values-en-rGB/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rGB/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Connected to device. Can\'t provide Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Not allowed by your organisation"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> from <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> from <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Connecting…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Available from <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Unknown"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-en-rIN/strings.xml b/libs/WifiTrackerLib/res/values-en-rIN/strings.xml
index 2a128180b..9761f9084 100644
--- a/libs/WifiTrackerLib/res/values-en-rIN/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rIN/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Connected to device. Can\'t provide Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Not allowed by your organisation"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> from <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> from <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Connecting…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Available from <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Unknown"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-en-rXC/strings.xml b/libs/WifiTrackerLib/res/values-en-rXC/strings.xml
index ebcd4c5ee..b8b58e9e9 100644
--- a/libs/WifiTrackerLib/res/values-en-rXC/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rXC/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‎‏‎Connected to device. Can\'t provide internet.‎‏‎‎‏‎"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎Low quality‎‏‎‎‏‎"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎Not allowed by your organization‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="NETWORK_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ from ‎‏‎‎‏‏‎<xliff:g id="MODEL_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="NETWORK_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ from ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎Connecting…‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎Available from ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎WPA/WPA2-EAP‎‏‎‎‏‎"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎WPA/WPA2-Enterprise‎‏‎‎‏‎"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‏‎‎WPA3-EAP‎‏‎‎‏‎"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎Wi‑Fi 6‎‏‎‎‏‎"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎WiGig‎‏‎‎‏‎"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎Wi‑Fi 7‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎Unknown‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎2.4 GHz‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎‎‏‎‎‎5 GHz‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎6 GHz‎‏‎‎‏‎"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‏‎,‎‏‎‎‏‎"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-es-rUS/strings.xml b/libs/WifiTrackerLib/res/values-es-rUS/strings.xml
index 1d5056892..126c0c814 100644
--- a/libs/WifiTrackerLib/res/values-es-rUS/strings.xml
+++ b/libs/WifiTrackerLib/res/values-es-rUS/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Se estableció conexión con el dispositivo. No se puede acceder a Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Baja calidad"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Tu organización no lo permite"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Estableciendo conexión…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponible desde <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Desconocido"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-es/strings.xml b/libs/WifiTrackerLib/res/values-es/strings.xml
index 4f1c9f480..94a47f1f2 100644
--- a/libs/WifiTrackerLib/res/values-es/strings.xml
+++ b/libs/WifiTrackerLib/res/values-es/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Conectado al dispositivo. Sin acceso a Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Calidad baja"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"No permitido por tu organización"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Conectando…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponible en <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Desconocido"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-et/strings.xml b/libs/WifiTrackerLib/res/values-et/strings.xml
index 6925e624b..3ecfca6fe 100644
--- a/libs/WifiTrackerLib/res/values-et/strings.xml
+++ b/libs/WifiTrackerLib/res/values-et/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Seadmega ühendatud. Internetiühendust ei saa luua."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kehva kvaliteediga"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Teie organisatsioon pole seda lubanud"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> mudelist <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> seadmest <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Ühendamine …"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Saadaval alates <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"6. põlvkonna WiFi"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"7. põlvkonna WiFi"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Tundmatu"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-eu/strings.xml b/libs/WifiTrackerLib/res/values-eu/strings.xml
index 98e19c738..9e5526f3c 100644
--- a/libs/WifiTrackerLib/res/values-eu/strings.xml
+++ b/libs/WifiTrackerLib/res/values-eu/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Gailura konektatuta. Ezin da Interenetarako sarbiderik eman."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kalitate txikia"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Erakundeak ez du baimenik eman"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> (<xliff:g id="MODEL_NAME">%2$s</xliff:g>)"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>)"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Konektatzen…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailuaren bidez erabilgarri"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2 EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2 enpresa"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3 EAP"</string>
@@ -71,7 +75,7 @@
<string name="wifitrackerlib_osu_completing_sign_up" msgid="4359503050543182480">"Izena ematen…"</string>
<string name="wifitrackerlib_osu_sign_up_failed" msgid="3964140125523395898">"Ezin izan da erregistratu. Berriro saiatzeko, ukitu hau."</string>
<string name="wifitrackerlib_osu_sign_up_complete" msgid="3279606633343124580">"Erregistratu da. Konektatzen…"</string>
- <string name="wifitrackerlib_imsi_protection_warning" msgid="7202210931586169466">"Gailuaren kokapenaren jarraipena egiteko balio duen SIM ID bat jasotzen du sare honek. "<annotation id="url">"Lortu informazio gehiago"</annotation></string>
+ <string name="wifitrackerlib_imsi_protection_warning" msgid="7202210931586169466">"Gailuaren kokapenaren jarraipena egiteko balio duen SIM identifikatzaile bat jasotzen du sare honek. "<annotation id="url">"Lortu informazio gehiago"</annotation></string>
<string name="wifitrackerlib_wifi_wont_autoconnect_for_now" msgid="4923161724964349851">"Oraingoz ez da automatikoki konektatuko wifira"</string>
<string name="wifitrackerlib_wifi_standard_unknown" msgid="8339211498889012019">"Ezezaguna"</string>
<string name="wifitrackerlib_wifi_standard_legacy" msgid="7760511318791054384">"Zaharkitua"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wifi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wifi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Ezezaguna"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-fa/strings.xml b/libs/WifiTrackerLib/res/values-fa/strings.xml
index 256a59822..67483d8ed 100644
--- a/libs/WifiTrackerLib/res/values-fa/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fa/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"به دستگاه متصل است. نمی‌تواند اینترنت ارائه دهد."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"کیفیت پایین"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"سازمان شما آن را مجاز نکرده است"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> از <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> از <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"درحال اتصال…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"ازطریق <xliff:g id="DEVICE_NAME">%1$s</xliff:g> دردسترس است"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"نامشخص"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"۲٫۴ گیگاهرتز"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"۵ گیگاهرتز"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"۶ گیگاهرتز"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"،"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-fi/strings.xml b/libs/WifiTrackerLib/res/values-fi/strings.xml
index 078eed4a6..b2ae60010 100644
--- a/libs/WifiTrackerLib/res/values-fi/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fi/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Yhdistetty laitteeseen. Ei voi muodostaa internetyhteyttä."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Heikko laatu"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Ei sallita organisaatiossasi"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> lähettäjältä <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> lähettäjältä <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Yhdistetään…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Saatavilla: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Tuntematon"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml b/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml
index 8e5e6028f..968ceaccf 100644
--- a/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Connecté à l\'appareil. Aucune connexion Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Faible qualité"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Non autorisé par votre organisation"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Connexion en cours…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Accessible à partir de <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-PAE"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-PAE"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Inconnue"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-fr/strings.xml b/libs/WifiTrackerLib/res/values-fr/strings.xml
index d66efe1bd..65b5f81c0 100644
--- a/libs/WifiTrackerLib/res/values-fr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fr/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Connecté à l\'appareil. Connexion Internet impossible."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Faible qualité"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Non autorisé par votre organisation"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> (<xliff:g id="MODEL_NAME">%2$s</xliff:g>)"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>)"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Connexion…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponible sur <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Inconnue"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-gl/strings.xml b/libs/WifiTrackerLib/res/values-gl/strings.xml
index 51b56747f..42b3b3bb0 100644
--- a/libs/WifiTrackerLib/res/values-gl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-gl/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Estableceuse conexión co dispositivo. Internet non está dispoñible."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Pouca calidade"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Non permitida pola túa organización"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Conectando…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Dispoñible en: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wifi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wifi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Descoñecida"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-gu/strings.xml b/libs/WifiTrackerLib/res/values-gu/strings.xml
index 58affba5f..f9a9199d7 100644
--- a/libs/WifiTrackerLib/res/values-gu/strings.xml
+++ b/libs/WifiTrackerLib/res/values-gu/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ડિવાઇસ સાથે કનેક્ટેડ છે. ઇન્ટરનેટ સેવા પ્રદાન કરી શકાતી નથી."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"ઓછી ક્વૉલિટી"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"તમારી સંસ્થા દ્વારા મંજૂર નથી"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> તરફથી <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> તરફથી <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"કનેક્ટ કરી રહ્યાં છીએ…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> પરથી ઉપલબ્ધ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-એન્ટરપ્રાઇઝ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"વાઇ-ફાઇ 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"વાઇ-ફાઇ 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"અજાણ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-hi/strings.xml b/libs/WifiTrackerLib/res/values-hi/strings.xml
index 541925808..ed504a0a4 100644
--- a/libs/WifiTrackerLib/res/values-hi/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hi/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"डिवाइस से कनेक्ट है. इंटरनेट सेवा उपलब्ध नहीं है."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"खराब कनेक्शन"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"आपके संगठन ने इसकी अनुमति नहीं दी है"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> की ओर से <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> की ओर से <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"कनेक्ट हो रहा है…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से उपलब्ध"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-एंटरप्राइज़"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"वाई-फ़ाई 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"वाई-फ़ाई 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"कोई जानकारी नहीं"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 गीगाहर्ट्ज़"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 गीगाहर्ट्ज़"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 गीगाहर्ट्ज़"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-hr/strings.xml b/libs/WifiTrackerLib/res/values-hr/strings.xml
index a80473754..8b4193f33 100644
--- a/libs/WifiTrackerLib/res/values-hr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hr/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Uspostavljena je veza s uređajem. Povezivanje s internetom nije moguće."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niska kvaliteta"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Vaša organizacija ne dopušta upotrebu"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>, <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Povezivanje…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Dostupno s uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Nepoznato"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-hu/strings.xml b/libs/WifiTrackerLib/res/values-hu/strings.xml
index 3f776ee29..bb7e00492 100644
--- a/libs/WifiTrackerLib/res/values-hu/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hu/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Csatlakoztatva az eszközhöz. Nincs internethozzáférés."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Gyenge minőségű"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Szervezete nem engedélyezte"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> a következőtől: <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> a következőtől: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Csatlakozás…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Innen áll rendelkezésre: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Ismeretlen"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-hy/strings.xml b/libs/WifiTrackerLib/res/values-hy/strings.xml
index a4603e5e3..f1749bb5b 100644
--- a/libs/WifiTrackerLib/res/values-hy/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hy/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Միացված է սարքին։ Հնարավոր չէ տրամադրել ինտերնետ կապ։"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ցածր որակ"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Թույլատրված չէ ձեր կազմակերպության կողմից"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>՝ <xliff:g id="MODEL_NAME">%2$s</xliff:g>-ից"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>՝ «<xliff:g id="DEVICE_NAME">%2$s</xliff:g>»-ից"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Միացում…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Հասանելի է <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքից"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Անհայտ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 ԳՀց"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 ԳՀց"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 ԳՀց"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-in/strings.xml b/libs/WifiTrackerLib/res/values-in/strings.xml
index 37c505c39..2fe6abe3e 100644
--- a/libs/WifiTrackerLib/res/values-in/strings.xml
+++ b/libs/WifiTrackerLib/res/values-in/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Terhubung ke perangkat. Tidak dapat menyediakan koneksi internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kualitas rendah"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Tidak diizinkan oleh organisasi Anda"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> dari <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> dari <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Menghubungkan…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Tersedia dari <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Tidak diketahui"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-is/strings.xml b/libs/WifiTrackerLib/res/values-is/strings.xml
index fd4240af1..ecfc40c94 100644
--- a/libs/WifiTrackerLib/res/values-is/strings.xml
+++ b/libs/WifiTrackerLib/res/values-is/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Tengt við tæki. Nettenging næst ekki."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lítil gæði"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Fyrirtækið leyfir þetta ekki"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> frá <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> frá <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Tengist…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Í boði frá <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Óþekkt"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-it/strings.xml b/libs/WifiTrackerLib/res/values-it/strings.xml
index 0e92a3a94..b21cf4c31 100644
--- a/libs/WifiTrackerLib/res/values-it/strings.xml
+++ b/libs/WifiTrackerLib/res/values-it/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Connessione al dispositivo effettuata. Impossibile accedere a Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Bassa qualità"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Uso non consentito dall\'organizzazione"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> da <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> da <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Connessione in corso…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponibile da <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Sconosciuta"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-iw/strings.xml b/libs/WifiTrackerLib/res/values-iw/strings.xml
index 1c33e1dd5..500806c8a 100644
--- a/libs/WifiTrackerLib/res/values-iw/strings.xml
+++ b/libs/WifiTrackerLib/res/values-iw/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"יש חיבור למכשיר. לא ניתן לספק חיבור לאינטרנט."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"איכות נמוכה"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"הארגון שלך לא מתיר את האפשרות הזו"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> מ-<xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> מהמכשיר <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"מתבצעת התחברות…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"מקור הרשת: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"לא ידוע"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"‎2.4GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"‎5GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6GHz‎"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ja/strings.xml b/libs/WifiTrackerLib/res/values-ja/strings.xml
index 3ae98f246..77b83c617 100644
--- a/libs/WifiTrackerLib/res/values-ja/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ja/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"デバイスに接続されました。インターネットにアクセスできません。"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"低品質"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"組織によって許可されていません"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> から <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>から <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"接続しています…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>から利用可能"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"不明"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"、"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ka/strings.xml b/libs/WifiTrackerLib/res/values-ka/strings.xml
index 54a95b151..e3f49b63c 100644
--- a/libs/WifiTrackerLib/res/values-ka/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ka/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"დაუკავშირდა მოწყობილობას. ინტერნეტის მიწოდება ვერ ხერხდება."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"დაბალი ხარისხი"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"არ არის დაშვებული თქვენი ორგანიზაციის მიერ"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>, წყარო: <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>, წყარო: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"უკავშირდება…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"ხელმისაწვდომია <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-დან"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"უცნობი"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 გჰც"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 გჰც"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 გჰც"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-kk/strings.xml b/libs/WifiTrackerLib/res/values-kk/strings.xml
index cea72b8e4..f29a0c5f5 100644
--- a/libs/WifiTrackerLib/res/values-kk/strings.xml
+++ b/libs/WifiTrackerLib/res/values-kk/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Құрылғыға қосылды. Интернетке қосылым жоқ."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Төмен сапа"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Ұйымыңыз рұқсат етпеген"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> ұсынған <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> ұсынған <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Қосылып жатыр…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> қолданбасында қолжетімді."</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Белгісіз"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 ГГц"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-km/strings.xml b/libs/WifiTrackerLib/res/values-km/strings.xml
index 9685852d9..0860dc5c3 100644
--- a/libs/WifiTrackerLib/res/values-km/strings.xml
+++ b/libs/WifiTrackerLib/res/values-km/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"បានភ្ជាប់​ជាមួយ​ឧបករណ៍។ មិនអាចផ្ដល់​អ៊ីនធឺណិតបានទេ។"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"គុណភាព​ទាប"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"មិនបាន​អនុញ្ញាត​ដោយ​ស្ថាប័ន​របស់​អ្នកទេ"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ពី <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ពី <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"កំពុងភ្ជាប់…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"អាចប្រើបានពី <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"មិនស្គាល់"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-kn/strings.xml b/libs/WifiTrackerLib/res/values-kn/strings.xml
index da0ae14f2..e47928534 100644
--- a/libs/WifiTrackerLib/res/values-kn/strings.xml
+++ b/libs/WifiTrackerLib/res/values-kn/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ಸಾಧನಕ್ಕೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ. ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕ ಒದಗಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"ಕಳಪೆ ಕನೆಕ್ಷನ್"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯಿಂದ ಅನುಮತಿಸಲಾಗಿಲ್ಲ"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> ನಿಂದ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> ನಿಂದ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"ಕನೆಕ್ಟ್ ಆಗುತ್ತಿದೆ…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ನಿಂದ ಲಭ್ಯವಿದೆ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-ಎಂಟರ್‌ಪ್ರೈಸ್"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"ವೈ-ಫೈ 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"ವೈ-ಫೈ 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"ಅಪರಿಚಿತ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ko/strings.xml b/libs/WifiTrackerLib/res/values-ko/strings.xml
index 55a231a9e..e812dfdd1 100644
--- a/libs/WifiTrackerLib/res/values-ko/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ko/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"기기에 연결되었습니다. 인터넷을 이용할 수 없습니다."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"품질 낮음"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"조직에서 허용하지 않음"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g>의 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>의 <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"연결 중…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>에서 사용 가능"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"알 수 없음"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ky/strings.xml b/libs/WifiTrackerLib/res/values-ky/strings.xml
index 6972c862d..2975c8122 100644
--- a/libs/WifiTrackerLib/res/values-ky/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ky/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Түзмөккө туташып турат. Интернет жок."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Начар сапат"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Уюмуңуз тыюу салган"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g>–<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>–<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Туташууда…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүндө жеткиликтүү"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Белгисиз"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 ГГц"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-lo/strings.xml b/libs/WifiTrackerLib/res/values-lo/strings.xml
index 4470c5a3c..0297e216e 100644
--- a/libs/WifiTrackerLib/res/values-lo/strings.xml
+++ b/libs/WifiTrackerLib/res/values-lo/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ເຊື່ອມຕໍ່ຫາອຸປະກອນແລ້ວ. ບໍ່ສາມາດໃຫ້ບໍລິການອິນເຕີເນັດໄດ້."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"ຄຸນນະພາບຕໍ່າ"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"ອົງການຂອງທ່ານບໍ່ອະນຸຍາດ"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ຈາກ <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> ຈາກ <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"ກຳລັງເຊື່ອມຕໍ່…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"ມີໃຫ້ຈາກ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"ບໍ່ຮູ້ຈັກ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-lt/strings.xml b/libs/WifiTrackerLib/res/values-lt/strings.xml
index 1ba619ae3..f64026009 100644
--- a/libs/WifiTrackerLib/res/values-lt/strings.xml
+++ b/libs/WifiTrackerLib/res/values-lt/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Prisijungta prie įrenginio. Nepavyksta prisijungti prie interneto."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Prastas ryšys"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Jūsų organizacijoje neleidžiama"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"„<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“ iš „<xliff:g id="MODEL_NAME">%2$s</xliff:g>“"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"„<xliff:g id="NETWORK_NAME">%1$s</xliff:g>“ iš <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Prisijungiama…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Pasiekiama iš „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA / WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA / „WPA2-Enterprise“"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Nežinoma"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-lv/strings.xml b/libs/WifiTrackerLib/res/values-lv/strings.xml
index 0316f2f0e..d1d25fef6 100644
--- a/libs/WifiTrackerLib/res/values-lv/strings.xml
+++ b/libs/WifiTrackerLib/res/values-lv/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Izveidots savienojums ar ierīci. Nav piekļuves internetam."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Zema kvalitāte"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Jūsu organizācija to neatļauj"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> no <xliff:g id="MODEL_NAME">%2$s</xliff:g> ierīces"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> no ierīces “<xliff:g id="DEVICE_NAME">%2$s</xliff:g>”"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Notiek savienojuma izveide…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Pieejams šādā ierīcē: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Nezināma"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-mk/strings.xml b/libs/WifiTrackerLib/res/values-mk/strings.xml
index f2d57199e..04f51884d 100644
--- a/libs/WifiTrackerLib/res/values-mk/strings.xml
+++ b/libs/WifiTrackerLib/res/values-mk/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Поврзано со уредот. Не може да се обезбеди интернет."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Лош квалитет"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Не е дозволено од вашата организација"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> од <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> од <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Се поврзува…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Достапно од <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Непознат"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ml/strings.xml b/libs/WifiTrackerLib/res/values-ml/strings.xml
index 45b6a1fb3..55c02089a 100644
--- a/libs/WifiTrackerLib/res/values-ml/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ml/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ഉപകരണത്തിലേക്ക് കണക്റ്റ് ചെയ്‌തു. ഇന്റർനെറ്റ് നൽകാനാകില്ല."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"കുറഞ്ഞ നിലവാരം"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"നിങ്ങളുടെ ഓർഗനൈസേഷൻ അനുവദിക്കുന്നില്ല"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> എന്നതിൽ നിന്നുള്ള <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> എന്നതിൽ നിന്നുള്ള <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"കണക്റ്റ് ചെയ്യുന്നു…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിൽ നിന്ന് ലഭ്യമാണ്"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-എന്റർപ്രൈസ്"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"വൈഫൈ 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"വൈഫൈ 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"അജ്ഞാതം"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-mn/strings.xml b/libs/WifiTrackerLib/res/values-mn/strings.xml
index 4dc67a40a..241ae3c70 100644
--- a/libs/WifiTrackerLib/res/values-mn/strings.xml
+++ b/libs/WifiTrackerLib/res/values-mn/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Төхөөрөмжид холбогдсон байна. Интернэт олгох боломжгүй."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Чанар муу"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Танай байгууллагаас зөвшөөрдөггүй"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g>-с ирсэн <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>-с ирсэн <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Холбогдож байна…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>-с ашиглах боломжтой"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Байгууллага"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Тодорхойгүй"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 ГГц"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-mr/strings.xml b/libs/WifiTrackerLib/res/values-mr/strings.xml
index b7d18796a..84e9662b4 100644
--- a/libs/WifiTrackerLib/res/values-mr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-mr/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"डिव्हाइसशी कनेक्ट केले. इंटरनेट उपलब्ध नाही."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"कमी गुणवत्ता"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"तुमच्या संस्थेने अनुमती दिलेली नाही"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> वरील <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> वरील <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"कनेक्ट करत आहे…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> वरून उपलब्ध आहे"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-एंटरप्राइझ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"वाय-फाय ६"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"वाय-फाय ७"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"अज्ञात"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"२.४ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"५ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"६ GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ms/strings.xml b/libs/WifiTrackerLib/res/values-ms/strings.xml
index 4f8d5c30c..d0474aede 100644
--- a/libs/WifiTrackerLib/res/values-ms/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ms/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Disambungkan pada peranti. Tidak dapat menyediakan Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kualiti rendah"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Tidak dibenarkan oleh organisasi anda"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> daripada <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> daripada <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Menyambung…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Tersedia daripada <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Tidak diketahui"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-my/strings.xml b/libs/WifiTrackerLib/res/values-my/strings.xml
index f5373d9c0..8ae822326 100644
--- a/libs/WifiTrackerLib/res/values-my/strings.xml
+++ b/libs/WifiTrackerLib/res/values-my/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"စက်ပစ္စည်းသို့ ချိတ်ဆက်ထားသည်။ အင်တာနက်ကို မပေးနိုင်ပါ။"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"အရည်အသွေး နိမ့်သည်"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> ထံမှ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> ထံမှ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"ချိတ်ဆက်နေသည်…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> တွင် ရနိုင်သည်"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"မသိ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"၂.၄ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"၅ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"၆ GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"၊"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-nb/strings.xml b/libs/WifiTrackerLib/res/values-nb/strings.xml
index 5a4bde0a8..e5f7d7f11 100644
--- a/libs/WifiTrackerLib/res/values-nb/strings.xml
+++ b/libs/WifiTrackerLib/res/values-nb/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Koblet til enheten. Kan ikke gi internettilgang."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lav kvalitet"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Ikke tillatt av organisasjonen din"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> fra <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> fra <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Kobler til …"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Tilgjengelig fra <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wifi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wifi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Ukjent"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ne/strings.xml b/libs/WifiTrackerLib/res/values-ne/strings.xml
index b8c06a065..e8a36f426 100644
--- a/libs/WifiTrackerLib/res/values-ne/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ne/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"डिभाइसमा कनेक्ट गरियो। इन्टरनेट उपलब्ध छैन।"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"न्यून गुणस्तर"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"तपाईंको सङ्गठनले अनुमति दिएको छैन"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> को <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> को <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"कनेक्ट गरिँदै छ…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> मा उपलब्ध"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-इन्टरप्राइज"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi ६"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi ७"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"अज्ञात"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"२.४ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"५ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"६ GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-nl/strings.xml b/libs/WifiTrackerLib/res/values-nl/strings.xml
index b13e03712..10c91199d 100644
--- a/libs/WifiTrackerLib/res/values-nl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-nl/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Verbonden met apparaat. Kan geen internet bieden."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lage kwaliteit"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Niet toegestaan door je organisatie"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> van <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> van <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Verbinden…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Beschikbaar vanaf <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wifi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wifi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Onbekend"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-or/strings.xml b/libs/WifiTrackerLib/res/values-or/strings.xml
index d68783ba3..9e992f962 100644
--- a/libs/WifiTrackerLib/res/values-or/strings.xml
+++ b/libs/WifiTrackerLib/res/values-or/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ଡିଭାଇସ୍ ସହ ସଂଯୋଗ କରାଯାଇଛି। ଇଣ୍ଟରନେଟ୍ ପ୍ରଦାନ କରାଯାଇପାରିବ ନାହିଁ।"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"ନିମ୍ନ ଗୁଣବତ୍ତା"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"ଆପଣଙ୍କ ସଂସ୍ଥା ଦ୍ୱାରା ଅନୁମତି ଦିଆଯାଏ ନାହିଁ"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g>ରୁ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>ରୁ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"କନେକ୍ଟ କରାଯାଉଛି…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ରୁ ଉପଲବ୍ଧ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"ୱାଇ-ଫାଇ 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"ୱାଇ-ଫାଇ 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"ଅଜଣା"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-pa/strings.xml b/libs/WifiTrackerLib/res/values-pa/strings.xml
index 0f6eba333..322e547c7 100644
--- a/libs/WifiTrackerLib/res/values-pa/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pa/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ। ਇੰਟਰਨੈੱਟ ਮੁਹੱਈਆ ਨਹੀਂ ਹੋ ਸਕਦਾ।"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"ਠੀਕ-ਠਾਕ ਕਨੈਕਸ਼ਨ"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸਦੀ ਆਗਿਆ ਨਹੀਂ ਦਿੱਤੀ ਗਈ"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> ਤੋਂ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> ਤੋਂ <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਤੋਂ ਉਪਲਬਧ ਹੈ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-ਐਂਟਰਪ੍ਰਾਈਜ਼"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"ਵਾਈ-ਫਾਈ 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"ਵਾਈ-ਫਾਈ 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"ਅਗਿਆਤ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-pl/strings.xml b/libs/WifiTrackerLib/res/values-pl/strings.xml
index e373831d9..19c7a0abc 100644
--- a/libs/WifiTrackerLib/res/values-pl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pl/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Podłączono do urządzenia. Nie można zapewnić dostępu do internetu."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niska jakość"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Niedozwolone przez Twoją organizację"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> z urządzenia <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> z urządzenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Łączę…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Sieć dostępna z urządzenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Brak informacji"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml b/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml
index 5dc66199c..b68025a68 100644
--- a/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Conectada ao dispositivo. Sem acesso à Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Conexão lenta"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Não permitido por sua organização"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> do <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> do dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Conectando…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponível no dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Desconhecido"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml b/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml
index d71585bc6..0ba5796f0 100644
--- a/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Ligado ao dispositivo. Não é possível disponibilizar Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Baixa qualidade"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Não é permitido pela sua organização"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"A ligar…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponível a partir de <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Desconhecido"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-pt/strings.xml b/libs/WifiTrackerLib/res/values-pt/strings.xml
index 5dc66199c..b68025a68 100644
--- a/libs/WifiTrackerLib/res/values-pt/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pt/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Conectada ao dispositivo. Sem acesso à Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Conexão lenta"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Não permitido por sua organização"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> do <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> do dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Conectando…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponível no dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Desconhecido"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ro/strings.xml b/libs/WifiTrackerLib/res/values-ro/strings.xml
index 1412d1329..9764d90cb 100644
--- a/libs/WifiTrackerLib/res/values-ro/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ro/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"S-a conectat la dispozitiv. Nu se poate stabili o conexiune la internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Calitate slabă"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Nu este acceptată de organizația ta"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de la <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> de la <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Se conectează…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Disponibilă de pe <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA / WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA / WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Necunoscută"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ru/strings.xml b/libs/WifiTrackerLib/res/values-ru/strings.xml
index 6e11b0de6..b25060f77 100644
--- a/libs/WifiTrackerLib/res/values-ru/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ru/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Подключено к устройству. Нет доступа к интернету."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"низкое качество"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Запрещено системным администратором"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"Сеть \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\", устройство <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"Сеть \"<xliff:g id="NETWORK_NAME">%1$s</xliff:g>\", устройство \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\""</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Подключение…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Доступно с устройства \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\""</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Неизвестно"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 ГГц"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-si/strings.xml b/libs/WifiTrackerLib/res/values-si/strings.xml
index 4860d0c04..b3ce814ba 100644
--- a/libs/WifiTrackerLib/res/values-si/strings.xml
+++ b/libs/WifiTrackerLib/res/values-si/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"උපාංගයට සම්බන්ධයි. අන්තර්ජාලය සැපයීමට නොහැකිය."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"අඩු ගුණත්වය"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"ඔබගේ සංවිධානය විසින් ඉඩ නොදේ"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> සිට <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> සිට <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"සම්බන්ධ වෙමින්…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> වෙතින් තිබේ"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"නොදනී"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-sk/strings.xml b/libs/WifiTrackerLib/res/values-sk/strings.xml
index 12048cd0b..c757dc71c 100644
--- a/libs/WifiTrackerLib/res/values-sk/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sk/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Pripojené k zariadeniu. Internet nie je možné poskytnúť."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nízka kvalita"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Nie je povolené vašou organizáciou"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> zariadenia <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> zariadenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Pripája sa…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"K dispozícii zo zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2‑EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2‑Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3‑EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Neznáme"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-sl/strings.xml b/libs/WifiTrackerLib/res/values-sl/strings.xml
index d300b3a7b..4ba04184c 100644
--- a/libs/WifiTrackerLib/res/values-sl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sl/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Povezava z napravo je vzpostavljena. Dostop do interneta ni na voljo."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nizka kakovost"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Organizacija tega ne dovoljuje."</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"Omrežje <xliff:g id="NETWORK_NAME">%1$s</xliff:g> (<xliff:g id="MODEL_NAME">%2$s</xliff:g>)"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"Omrežje <xliff:g id="NETWORK_NAME">%1$s</xliff:g> (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>)"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Vzpostavljanje povezave …"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Na voljo iz naprave <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Neznano"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-sq/strings.xml b/libs/WifiTrackerLib/res/values-sq/strings.xml
index ff71056bb..f4d9db1e4 100644
--- a/libs/WifiTrackerLib/res/values-sq/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sq/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"U lidh me pajisjen. Interneti nuk mund të ofrohet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Cilësi e ulët"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Nuk lejohet nga organizata jote"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> nga <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> nga <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Po lidhet…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Ofrohet nga <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"I panjohur"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-sr/strings.xml b/libs/WifiTrackerLib/res/values-sr/strings.xml
index 042353409..b487cc5e4 100644
--- a/libs/WifiTrackerLib/res/values-sr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sr/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Уређај је повезан. Пружање интернета није успело."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Лош квалитет"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Не дозвољава ваша организација"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> – <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> – <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Повезује се…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Доступно са уређаја <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"WiFi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"WiFi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Непознато"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-sv/strings.xml b/libs/WifiTrackerLib/res/values-sv/strings.xml
index 11baf3056..53fee4187 100644
--- a/libs/WifiTrackerLib/res/values-sv/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sv/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Ansluten till enheten. Det går inte att ansluta till internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Låg kvalitet"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Tillåts inte av din organisation"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> från <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> från <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Ansluter …"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Tillgängligt från <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2 Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wifi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wifi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Okänt"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-sw/strings.xml b/libs/WifiTrackerLib/res/values-sw/strings.xml
index a7c1bd399..25dde5d89 100644
--- a/libs/WifiTrackerLib/res/values-sw/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sw/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Kifaa kimeunganishwa. Imeshindwa kusambaza intaneti."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ubora wa chini"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Shirika lako haliruhusu"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> kutoka kwenye <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> kutoka kwenye <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Inaunganisha…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Unapatikana kwenye <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi-Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Haijulikani"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"GHz 2.4"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"GHz 5"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"GHz 6"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ta/strings.xml b/libs/WifiTrackerLib/res/values-ta/strings.xml
index b6f90123b..7261376ee 100644
--- a/libs/WifiTrackerLib/res/values-ta/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ta/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"சாதனத்துடன் இணைக்கப்பட்டது. இணைய இணைப்பு இல்லை."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"குறைந்த தரம்"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"உங்கள் நிறுவனத்தால் அனுமதிக்கப்படவில்லை"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> வழங்கும் <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> வழங்கும் <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"இணைக்கிறது…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தில் இருந்து கிடைக்கும்"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"வைஃபை 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"வைஃபை 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"தெரியவில்லை"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-te/strings.xml b/libs/WifiTrackerLib/res/values-te/strings.xml
index db7a52953..cc16b49be 100644
--- a/libs/WifiTrackerLib/res/values-te/strings.xml
+++ b/libs/WifiTrackerLib/res/values-te/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"పరికరానికి కనెక్ట్ అయింది. ఇంటర్నెట్‌ను అందిచడం సాధ్యం కాదు."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"తక్కువ క్వాలిటీ"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"మీ సంస్థచే అనుమతించబడదు"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> నుండి <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> నుండి <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"కనెక్ట్ అవుతోంది…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> నుండి అందుబాటులో ఉంది"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"తెలియదు"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-th/strings.xml b/libs/WifiTrackerLib/res/values-th/strings.xml
index b7b05cdc8..3d1c33f41 100644
--- a/libs/WifiTrackerLib/res/values-th/strings.xml
+++ b/libs/WifiTrackerLib/res/values-th/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"เชื่อมต่ออุปกรณ์แล้ว แต่ไม่มีอินเทอร์เน็ต"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"คุณภาพต่ำ"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"องค์กรของคุณไม่อนุญาต"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> จาก <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> จาก <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"กำลังเชื่อมต่อ…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"พร้อมใช้งานจาก <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"ไม่ทราบ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-tl/strings.xml b/libs/WifiTrackerLib/res/values-tl/strings.xml
index db9337de4..0333eb7dd 100644
--- a/libs/WifiTrackerLib/res/values-tl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-tl/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Nakakonekta sa device. Hindi makapagbigay ng internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Mababang kalidad"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Hindi pinapayagan ng iyong organisasyon"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> mula sa <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> mula sa <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Kumokonekta…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Available mula sa <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Hindi alam"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-tr/strings.xml b/libs/WifiTrackerLib/res/values-tr/strings.xml
index 4fef5a0ec..5fe75160d 100644
--- a/libs/WifiTrackerLib/res/values-tr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-tr/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Cihaza bağlandı. İnternet bağlantısı sağlanamıyor."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Düşük kalite"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Kuruluşunuz tarafından izin verilmiyor"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> tarafından gönderilen <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> tarafından gönderilen <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Bağlanıyor…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazında erişilebilir"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Bilinmiyor"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-uk/strings.xml b/libs/WifiTrackerLib/res/values-uk/strings.xml
index fb8cc2887..a9efd5959 100644
--- a/libs/WifiTrackerLib/res/values-uk/strings.xml
+++ b/libs/WifiTrackerLib/res/values-uk/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Підключено до пристрою. Інтернет-з\'єднання відсутнє."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Низька якість"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Заборонено у вашій організації"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> з пристрою <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> з пристрою \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\""</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Підключення…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Доступно з пристрою \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\""</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Невідомо"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 ГГц"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 ГГц"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-ur/strings.xml b/libs/WifiTrackerLib/res/values-ur/strings.xml
index 1b4428ba3..22d944ce3 100644
--- a/libs/WifiTrackerLib/res/values-ur/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ur/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"آلے سے منسلک ہے۔ انٹرنیٹ فراہم نہیں کیا جا سکتا۔"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"ادنٰی معیار"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"آپ کی تنظیم کی طرف سے اجازت نہیں ہے"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> منجانب <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> منجانب <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"منسلک ہو رہا ہے…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> کی طرف سے دستیاب ہیں"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"‏WPA/WPA2 انٹرپرائز"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"نامعلوم"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4‎ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5‎ GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"‏GHz ‏6"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"،"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-uz/strings.xml b/libs/WifiTrackerLib/res/values-uz/strings.xml
index 7d19e87c9..f5011c9ab 100644
--- a/libs/WifiTrackerLib/res/values-uz/strings.xml
+++ b/libs/WifiTrackerLib/res/values-uz/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Qurilmaga ulandi. Internetga ulanmagan."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Sifati past"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Tashkilotingiz ruxsat bermagan"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="MODEL_NAME">%2$s</xliff:g> <xliff:g id="NETWORK_NAME">%1$s</xliff:g> yubordi"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> <xliff:g id="NETWORK_NAME">%1$s</xliff:g> yubordi"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Ulanmoqda…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Sotuvga chiqadi: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Noaniq"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GGs"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GGs"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GGs"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-vi/strings.xml b/libs/WifiTrackerLib/res/values-vi/strings.xml
index 91d25b361..618891b1c 100644
--- a/libs/WifiTrackerLib/res/values-vi/strings.xml
+++ b/libs/WifiTrackerLib/res/values-vi/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Đã kết nối với thiết bị. Không thể cung cấp Internet."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Chất lượng thấp"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Không được tổ chức của bạn cho phép"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> trên <xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> trên <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Đang kết nối…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Có từ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Không rõ"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2,4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml b/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml
index d11f8c84d..5be532e2e 100644
--- a/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml
+++ b/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"已连接到设备,但无法提供互联网连接。"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"质量不佳"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"您的组织不允许使用"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"来自<xliff:g id="MODEL_NAME">%2$s</xliff:g>的<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"来自“<xliff:g id="DEVICE_NAME">%2$s</xliff:g>”的<xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"正在连接…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"来自以下设备:<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"未知"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"、"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml b/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml
index 90141c187..3b2aae751 100644
--- a/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml
+++ b/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"已連接裝置,但無法提供互聯網連線。"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"品質欠佳"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"你的機構禁止使用"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"來自「<xliff:g id="MODEL_NAME">%2$s</xliff:g>」的「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"來自「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」的「<xliff:g id="NETWORK_NAME">%1$s</xliff:g>」"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"正在連線…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"網絡來源:<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"不明"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"、"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml b/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml
index 161b88952..ac7f36d09 100644
--- a/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml
+++ b/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"已連上裝置,但無法提供網際網路連線。"</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"品質不佳"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"貴機構禁止使用"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> (來自<xliff:g id="MODEL_NAME">%2$s</xliff:g>)"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> (來自<xliff:g id="DEVICE_NAME">%2$s</xliff:g>)"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"連線中…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"網路來源:<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"Wi‑Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"不明"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">"、"</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values-zu/strings.xml b/libs/WifiTrackerLib/res/values-zu/strings.xml
index e8b67992c..49566b4f5 100644
--- a/libs/WifiTrackerLib/res/values-zu/strings.xml
+++ b/libs/WifiTrackerLib/res/values-zu/strings.xml
@@ -44,6 +44,10 @@
<string name="wifitrackerlib_wifi_connected_cannot_provide_internet" msgid="3803471522215612745">"Ixhunywe kudivayisi. Ayikwazi ukunikeza i-inthanethi."</string>
<string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ikhwalithi ephansi"</string>
<string name="wifitrackerlib_admin_restricted_network" msgid="5439914801076897515">"Ayivunyelwe yinhlangano yakho"</string>
+ <string name="wifitrackerlib_hotspot_network_summary" msgid="7661086683527884190">"I-<xliff:g id="NETWORK_NAME">%1$s</xliff:g> evela ku-<xliff:g id="MODEL_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_alternate" msgid="4966814473758893807">"I-<xliff:g id="NETWORK_NAME">%1$s</xliff:g> evela ku-<xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+ <string name="wifitrackerlib_hotspot_network_connecting" msgid="2072252282318270780">"Iyaxhuma…"</string>
+ <string name="wifitrackerlib_known_network_summary" msgid="6035425130009353268">"Kutholakala ukusukela ku-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2" msgid="4815223667006927841">"I-WPA/WPA2-EAP"</string>
<string name="wifitrackerlib_wifi_security_eap_wpa_wpa2" msgid="6425661975745405271">"I-WPA/WPA2-Enterprise"</string>
<string name="wifitrackerlib_wifi_security_short_eap_wpa3" msgid="6210273302049534874">"I-WPA3-EAP"</string>
@@ -80,4 +84,9 @@
<string name="wifitrackerlib_wifi_standard_11ax" msgid="4071875115186480116">"I-Wi-Fi 6"</string>
<string name="wifitrackerlib_wifi_standard_11ad" msgid="4955749187120493383">"I-WiGig"</string>
<string name="wifitrackerlib_wifi_standard_11be" msgid="1886834788680487835">"I-Wi‑Fi 7"</string>
+ <string name="wifitrackerlib_wifi_band_unknown" msgid="5576746583228374334">"Akwaziwa"</string>
+ <string name="wifitrackerlib_wifi_band_24_ghz" msgid="5374362780653321244">"2.4 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_5_ghz" msgid="2179047349922091556">"5 GHz"</string>
+ <string name="wifitrackerlib_wifi_band_6_ghz" msgid="6532408050869498777">"6 GHz"</string>
+ <string name="wifitrackerlib_multiband_separator" msgid="2696920984391378575">","</string>
</resources>
diff --git a/libs/WifiTrackerLib/res/values/strings.xml b/libs/WifiTrackerLib/res/values/strings.xml
index e1d53f500..691fb214f 100644
--- a/libs/WifiTrackerLib/res/values/strings.xml
+++ b/libs/WifiTrackerLib/res/values/strings.xml
@@ -118,6 +118,18 @@
<!-- Summary for admin restricted networks [CHAR LIMIT=NONE] -->
<string name="wifitrackerlib_admin_restricted_network">Not allowed by your organization</string>
+ <!-- Summary for a hotspot network (used on "Internet" page) [CHAR LIMIT=NONE] -->
+ <string name="wifitrackerlib_hotspot_network_summary"><xliff:g id="network name" example="Google Fi">%1$s</xliff:g> from <xliff:g id="model name" example="Pixel 7">%2$s</xliff:g></string>
+
+ <!-- Alternate summary for a hotspot network (used on "Network & internet" page) [CHAR LIMIT=NONE] -->
+ <string name="wifitrackerlib_hotspot_network_alternate"><xliff:g id="network name" example="Google Fi">%1$s</xliff:g> from <xliff:g id="device name" example="Matt's Phone">%2$s</xliff:g></string>
+
+ <!-- Summary for a hotspot network while connecting (used on "Internet" page) [CHAR LIMIT=NONE] -->
+ <string name="wifitrackerlib_hotspot_network_connecting">Connecting\u2026</string>
+
+ <!-- Summary for a known network (used on "Internet" page) [CHAR LIMIT=NONE] -->
+ <string name="wifitrackerlib_known_network_summary">Available from <xliff:g id="device name" example="Matt's Phone">%1$s</xliff:g></string>
+
<!-- Concise terminology for wifi with WPA/WPA2 802.1x EAP security [CHAR LIMIT=40] -->
<string name="wifitrackerlib_wifi_security_short_eap_wpa_wpa2">WPA/WPA2-EAP</string>
@@ -225,4 +237,15 @@
<string name="wifitrackerlib_wifi_standard_11ad">WiGig</string>
<!-- Summary for the Wi-Fi standard WIFI_STANDARD_11BE [CHAR LIMIT=50]-->
<string name="wifitrackerlib_wifi_standard_11be">Wi\u2011Fi 7</string>
+
+ <!-- Summary for an unknown Wi-Fi band [CHAR LIMIT=50]-->
+ <string name="wifitrackerlib_wifi_band_unknown">Unknown</string>
+ <!-- Summary for the Wi-Fi 2.4Ghz band [CHAR LIMIT=50]-->
+ <string name="wifitrackerlib_wifi_band_24_ghz">2.4 GHz</string>
+ <!-- Summary for the Wi-Fi 5Ghz band [CHAR LIMIT=50]-->
+ <string name="wifitrackerlib_wifi_band_5_ghz">5 GHz</string>
+ <!-- Summary for the Wi-Fi 6Ghz band [CHAR LIMIT=50]-->
+ <string name="wifitrackerlib_wifi_band_6_ghz">6 GHz</string>
+ <!-- Separator between Wi-Fi bands in a list [CHAR LIMIT=50]-->
+ <string name="wifitrackerlib_multiband_separator">, </string>
</resources>
diff --git a/libs/WifiTrackerLib/sdk_src/src/com/android/wifitrackerlib/NonSdkApiWrapper.java b/libs/WifiTrackerLib/sdk_src/src/com/android/wifitrackerlib/NonSdkApiWrapper.java
index 8233fb032..52c51557b 100644
--- a/libs/WifiTrackerLib/sdk_src/src/com/android/wifitrackerlib/NonSdkApiWrapper.java
+++ b/libs/WifiTrackerLib/sdk_src/src/com/android/wifitrackerlib/NonSdkApiWrapper.java
@@ -23,7 +23,6 @@ import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiInfo;
-import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -36,6 +35,10 @@ import androidx.annotation.Nullable;
* library over to their own codebase.
*/
class NonSdkApiWrapper {
+ private NonSdkApiWrapper() {
+ // Empty constructor to make this class non-instantiable.
+ }
+
/**
* Starts the System captive portal app.
*/
@@ -54,12 +57,12 @@ class NonSdkApiWrapper {
}
/**
- * Returns whether or not the network capabilities is determined to be VCN over Wi-Fi or not.
+ * Tries to get WifiInfo from network capabilities if it is VCN-over-Wifi.
*/
- static boolean isVcnOverWifi(@NonNull NetworkCapabilities networkCapabilities) {
+ static WifiInfo getVcnWifiInfo(@NonNull NetworkCapabilities networkCapabilities) {
// This is only useful for treating CELLULAR over WIFI as a carrier merged network in
// provider model Settings. Since SUW doesn't use the provider model, this is not used.
- return false;
+ return null;
}
/**
@@ -71,19 +74,6 @@ class NonSdkApiWrapper {
}
/**
- * Registers the system default network callback.
- */
- static void registerSystemDefaultNetworkCallback(
- @NonNull ConnectivityManager connectivityManager,
- @NonNull ConnectivityManager.NetworkCallback callback,
- @NonNull Handler handler) {
- // registerSystemDefaultNetworkCallback does not have visibility to non-updatable modules,
- // so we have to use the regular registerDefaultNetworkCallback here.
- // TODO(b/230643853): See if we can add registerSystemDefaultNetworkCallback to the SDK.
- connectivityManager.registerDefaultNetworkCallback(callback, handler);
- }
-
- /**
* Returns true if the WifiInfo is for the primary network, false otherwise.
*/
static boolean isPrimary(@NonNull WifiInfo wifiInfo) {
@@ -94,6 +84,16 @@ class NonSdkApiWrapper {
}
/**
+ * Returns true if the NetworkCapabilities is OEM_PAID or OEM_PRIVATE
+ */
+ static boolean isOemCapabilities(@NonNull NetworkCapabilities capabilities) {
+ // SUW can't access NET_CAPABILITY_OEM_PAID or NET_CAPABILITY_OEM_PRIVATE since they aren't
+ // public APIs. Return false here since we don't need to worry about secondary OEM networks
+ // in SUW for now.
+ return false;
+ }
+
+ /**
* Returns the {@link WifiSsidPolicy} of the device.
*/
@Nullable
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
index 68bada51e..5f1abd9a5 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
@@ -16,10 +16,12 @@
package com.android.wifitrackerlib;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.os.Build.VERSION_CODES;
+import android.annotation.TargetApi;
+import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -30,9 +32,16 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.TransportInfo;
-import android.net.wifi.WifiInfo;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiScanner;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
import android.os.Handler;
import android.os.Looper;
import android.telephony.SubscriptionManager;
@@ -44,11 +53,15 @@ import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import androidx.core.os.BuildCompat;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import java.time.Clock;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
/**
* Base class for WifiTracker functionality.
@@ -75,11 +88,13 @@ import java.time.Clock;
* the worker thread and consumed by the main thread.
*/
-public class BaseWifiTracker implements LifecycleObserver {
+public class BaseWifiTracker {
private final String mTag;
private static boolean sVerboseLogging;
+ public static boolean mEnableSharedConnectivityFeature = false;
+
public static boolean isVerboseLoggingEnabled() {
return BaseWifiTracker.sVerboseLogging;
}
@@ -102,11 +117,7 @@ public class BaseWifiTracker implements LifecycleObserver {
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
mWifiState = intent.getIntExtra(
WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
- if (mWifiState == WifiManager.WIFI_STATE_ENABLED) {
- mScanner.start();
- } else {
- mScanner.stop();
- }
+ mScanner.onWifiStateChanged(mWifiState == WifiManager.WIFI_STATE_ENABLED);
notifyOnWifiStateChanged();
handleWifiStateChangedAction();
} else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
@@ -115,8 +126,6 @@ public class BaseWifiTracker implements LifecycleObserver {
handleConfiguredNetworksChangedAction(intent);
} else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
handleNetworkStateChangedAction(intent);
- } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
- handleRssiChangedAction();
} else if (TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED.equals(action)) {
handleDefaultSubscriptionChanged(intent.getIntExtra(
"subscription", SubscriptionManager.INVALID_SUBSCRIPTION_ID));
@@ -128,6 +137,7 @@ public class BaseWifiTracker implements LifecycleObserver {
protected final WifiTrackerInjector mInjector;
protected final Context mContext;
+ protected final @NonNull ActivityManager mActivityManager;
protected final WifiManager mWifiManager;
protected final ConnectivityManager mConnectivityManager;
protected final ConnectivityDiagnosticsManager mConnectivityDiagnosticsManager;
@@ -136,10 +146,8 @@ public class BaseWifiTracker implements LifecycleObserver {
protected final long mMaxScanAgeMillis;
protected final long mScanIntervalMillis;
protected final ScanResultUpdater mScanResultUpdater;
- protected boolean mIsWifiValidated;
- protected boolean mIsWifiDefaultRoute;
- protected boolean mIsCellDefaultRoute;
- protected Network mPrimaryNetwork;
+
+ @Nullable protected SharedConnectivityManager mSharedConnectivityManager = null;
// Network request for listening on changes to Wifi link properties and network capabilities
// such as captive portal availability.
@@ -147,82 +155,46 @@ public class BaseWifiTracker implements LifecycleObserver {
.clearCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.addTransportType(TRANSPORT_WIFI)
+ .addTransportType(TRANSPORT_CELLULAR) // For VCN-over-Wifi
.build();
private final ConnectivityManager.NetworkCallback mNetworkCallback =
- new ConnectivityManager.NetworkCallback() {
+ new ConnectivityManager.NetworkCallback(
+ ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
@Override
@WorkerThread
public void onLinkPropertiesChanged(@NonNull Network network,
@NonNull LinkProperties lp) {
- if (!isPrimaryWifiNetwork(
- mConnectivityManager.getNetworkCapabilities(network))) {
- return;
- }
- mPrimaryNetwork = network;
- handleLinkPropertiesChanged(lp);
+ handleLinkPropertiesChanged(network, lp);
}
@Override
@WorkerThread
public void onCapabilitiesChanged(@NonNull Network network,
@NonNull NetworkCapabilities networkCapabilities) {
- if (!isPrimaryWifiNetwork(networkCapabilities)) {
- return;
- }
- mPrimaryNetwork = network;
- final boolean oldWifiValidated = mIsWifiValidated;
- mIsWifiValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
- if (isVerboseLoggingEnabled() && mIsWifiValidated != oldWifiValidated) {
- Log.v(mTag, "Is Wifi validated: " + mIsWifiValidated);
- }
- handleNetworkCapabilitiesChanged(networkCapabilities);
+ handleNetworkCapabilitiesChanged(network, networkCapabilities);
}
@Override
@WorkerThread
public void onLost(@NonNull Network network) {
- if (!isPrimaryWifiNetwork(
- mConnectivityManager.getNetworkCapabilities(network))) {
- return;
- }
- mIsWifiValidated = false;
- mPrimaryNetwork = null;
+ handleNetworkLost(network);
}
};
private final ConnectivityManager.NetworkCallback mDefaultNetworkCallback =
- new ConnectivityManager.NetworkCallback() {
+ new ConnectivityManager.NetworkCallback(
+ ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
@Override
@WorkerThread
public void onCapabilitiesChanged(@NonNull Network network,
@NonNull NetworkCapabilities networkCapabilities) {
- final boolean oldWifiDefault = mIsWifiDefaultRoute;
- final boolean oldCellDefault = mIsCellDefaultRoute;
- // raw Wifi or VPN-over-Wifi or VCN-over-Wifi is default => Wifi is default.
- mIsWifiDefaultRoute = networkCapabilities.hasTransport(TRANSPORT_WIFI)
- || NonSdkApiWrapper.isVcnOverWifi(networkCapabilities);
- mIsCellDefaultRoute = !mIsWifiDefaultRoute
- && networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
- if (mIsWifiDefaultRoute != oldWifiDefault
- || mIsCellDefaultRoute != oldCellDefault) {
- if (isVerboseLoggingEnabled()) {
- Log.v(mTag, "Wifi is the default route: " + mIsWifiDefaultRoute);
- Log.v(mTag, "Cell is the default route: " + mIsCellDefaultRoute);
- }
- handleDefaultRouteChanged();
- }
+ handleDefaultNetworkCapabilitiesChanged(network, networkCapabilities);
}
@WorkerThread
public void onLost(@NonNull Network network) {
- mIsWifiDefaultRoute = false;
- mIsCellDefaultRoute = false;
- if (isVerboseLoggingEnabled()) {
- Log.v(mTag, "Wifi is the default route: false");
- Log.v(mTag, "Cell is the default route: false");
- }
- handleDefaultRouteChanged();
+ handleDefaultNetworkLost();
}
};
@@ -236,36 +208,77 @@ public class BaseWifiTracker implements LifecycleObserver {
}
};
- private boolean isPrimaryWifiNetwork(@Nullable NetworkCapabilities networkCapabilities) {
- if (networkCapabilities == null) {
- return false;
- }
- final TransportInfo transportInfo = networkCapabilities.getTransportInfo();
- if (!(transportInfo instanceof WifiInfo)) {
- return false;
- }
- return NonSdkApiWrapper.isPrimary((WifiInfo) transportInfo);
- }
-
- protected void updateDefaultRouteInfo() {
- final NetworkCapabilities defaultNetworkCapabilities = mConnectivityManager
- .getNetworkCapabilities(mConnectivityManager.getActiveNetwork());
- if (defaultNetworkCapabilities != null) {
- mIsWifiDefaultRoute = defaultNetworkCapabilities.hasTransport(TRANSPORT_WIFI);
- mIsCellDefaultRoute = defaultNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR);
- } else {
- mIsWifiDefaultRoute = false;
- mIsCellDefaultRoute = false;
+ private final Executor mConnectivityDiagnosticsExecutor = new Executor() {
+ @Override
+ public void execute(Runnable command) {
+ mWorkerHandler.post(command);
}
- if (isVerboseLoggingEnabled()) {
- Log.v(mTag, "Wifi is the default route: " + mIsWifiDefaultRoute);
- Log.v(mTag, "Cell is the default route: " + mIsCellDefaultRoute);
+ };
+
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ private final Executor mSharedConnectivityExecutor = new Executor() {
+ @Override
+ public void execute(Runnable command) {
+ mWorkerHandler.post(command);
}
+ };
+
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Nullable
+ private SharedConnectivityClientCallback mSharedConnectivityCallback = null;
+
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @NonNull
+ private SharedConnectivityClientCallback createSharedConnectivityCallback() {
+ return new SharedConnectivityClientCallback() {
+ @Override
+ public void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> networks) {
+ handleHotspotNetworksUpdated(networks);
+ }
+
+ @Override
+ public void onKnownNetworksUpdated(@NonNull List<KnownNetwork> networks) {
+ handleKnownNetworksUpdated(networks);
+ }
+
+ @Override
+ public void onSharedConnectivitySettingsChanged(
+ @NonNull SharedConnectivitySettingsState state) {
+ handleSharedConnectivitySettingsChanged(state);
+ }
+
+ @Override
+ public void onHotspotNetworkConnectionStatusChanged(
+ @NonNull HotspotNetworkConnectionStatus status) {
+ handleHotspotNetworkConnectionStatusChanged(status);
+ }
+
+ @Override
+ public void onKnownNetworkConnectionStatusChanged(
+ @NonNull KnownNetworkConnectionStatus status) {
+ handleKnownNetworkConnectionStatusChanged(status);
+ }
+
+ @Override
+ public void onServiceConnected() {
+ handleServiceConnected();
+ }
+
+ @Override
+ public void onServiceDisconnected() {
+ handleServiceDisconnected();
+ }
+
+ @Override
+ public void onRegisterCallbackFailed(Exception exception) {
+ handleRegisterCallbackFailed(exception);
+ }
+ };
}
/**
* Constructor for BaseWifiTracker.
- * @param wifiTrackerInjector injector for commonly referenced objects.
+ * @param injector Injector for commonly referenced objects.
* @param lifecycle Lifecycle this is tied to for lifecycle callbacks.
* @param context Context for registering broadcast receiver and for resource strings.
* @param wifiManager Provides all Wi-Fi info.
@@ -276,6 +289,7 @@ public class BaseWifiTracker implements LifecycleObserver {
* @param maxScanAgeMillis Max age for tracked WifiEntries.
* @param scanIntervalMillis Interval between initiating scans.
*/
+ @SuppressWarnings("StaticAssignmentInConstructor")
BaseWifiTracker(
@NonNull WifiTrackerInjector injector,
@NonNull Lifecycle lifecycle, @NonNull Context context,
@@ -289,12 +303,35 @@ public class BaseWifiTracker implements LifecycleObserver {
BaseWifiTrackerCallback listener,
String tag) {
mInjector = injector;
- lifecycle.addObserver(this);
+ mActivityManager = context.getSystemService(ActivityManager.class);
+ lifecycle.addObserver(new LifecycleObserver() {
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ @MainThread
+ public void onStart() {
+ BaseWifiTracker.this.onStart();
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ @MainThread
+ public void onStop() {
+ BaseWifiTracker.this.onStop();
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+ @MainThread
+ public void onDestroy() {
+ BaseWifiTracker.this.onDestroy();
+ }
+ });
mContext = context;
mWifiManager = wifiManager;
mConnectivityManager = connectivityManager;
mConnectivityDiagnosticsManager =
context.getSystemService(ConnectivityDiagnosticsManager.class);
+ if (mEnableSharedConnectivityFeature && BuildCompat.isAtLeastU()) {
+ mSharedConnectivityManager = context.getSystemService(SharedConnectivityManager.class);
+ mSharedConnectivityCallback = createSharedConnectivityCallback();
+ }
mMainHandler = mainHandler;
mWorkerHandler = workerHandler;
mMaxScanAgeMillis = maxScanAgeMillis;
@@ -306,32 +343,38 @@ public class BaseWifiTracker implements LifecycleObserver {
maxScanAgeMillis + scanIntervalMillis);
mScanner = new BaseWifiTracker.Scanner(workerHandler.getLooper());
sVerboseLogging = mWifiManager.isVerboseLoggingEnabled();
- updateDefaultRouteInfo();
}
/**
* Registers the broadcast receiver and network callbacks and starts the scanning mechanism.
*/
- @OnLifecycleEvent(Lifecycle.Event.ON_START)
@MainThread
public void onStart() {
+ if (isVerboseLoggingEnabled()) {
+ Log.v(mTag, "onStart");
+ }
+ mScanner.onStart();
mWorkerHandler.post(() -> {
- updateDefaultRouteInfo();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(mBroadcastReceiver, filter,
/* broadcastPermission */ null, mWorkerHandler);
mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
mWorkerHandler);
+ mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback,
+ mWorkerHandler);
mConnectivityDiagnosticsManager.registerConnectivityDiagnosticsCallback(mNetworkRequest,
- command -> mWorkerHandler.post(command), mConnectivityDiagnosticsCallback);
- NonSdkApiWrapper.registerSystemDefaultNetworkCallback(
- mConnectivityManager, mDefaultNetworkCallback, mWorkerHandler);
+ mConnectivityDiagnosticsExecutor, mConnectivityDiagnosticsCallback);
+ if (mSharedConnectivityManager != null && mSharedConnectivityCallback != null
+ && BuildCompat.isAtLeastU()) {
+ mSharedConnectivityManager.registerCallback(mSharedConnectivityExecutor,
+ mSharedConnectivityCallback);
+ }
handleOnStart();
mIsInitialized = true;
});
@@ -340,17 +383,28 @@ public class BaseWifiTracker implements LifecycleObserver {
/**
* Unregisters the broadcast receiver, network callbacks, and pauses the scanning mechanism.
*/
- @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
@MainThread
public void onStop() {
+ if (isVerboseLoggingEnabled()) {
+ Log.v(mTag, "onStop");
+ }
+ mScanner.onStop();
mWorkerHandler.post(() -> {
- mScanner.stop();
try {
mContext.unregisterReceiver(mBroadcastReceiver);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mConnectivityManager.unregisterNetworkCallback(mDefaultNetworkCallback);
mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback);
+ if (mSharedConnectivityManager != null && mSharedConnectivityCallback != null
+ && BuildCompat.isAtLeastU()) {
+ boolean result =
+ mSharedConnectivityManager.unregisterCallback(
+ mSharedConnectivityCallback);
+ if (!result) {
+ Log.e(mTag, "onStop: unregisterCallback failed");
+ }
+ }
} catch (IllegalArgumentException e) {
// Already unregistered in onDestroyed().
}
@@ -361,15 +415,23 @@ public class BaseWifiTracker implements LifecycleObserver {
* Unregisters the broadcast receiver network callbacks in case the Activity is destroyed before
* the worker thread runnable posted in onStop() runs.
*/
- @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
@MainThread
- public void onDestroyed() {
+ public void onDestroy() {
try {
mContext.unregisterReceiver(mBroadcastReceiver);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mConnectivityManager.unregisterNetworkCallback(mDefaultNetworkCallback);
mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback);
+ if (mSharedConnectivityManager != null && mSharedConnectivityCallback != null
+ && BuildCompat.isAtLeastU()) {
+ boolean result =
+ mSharedConnectivityManager.unregisterCallback(
+ mSharedConnectivityCallback);
+ if (!result) {
+ Log.e(mTag, "onDestroyed: unregisterCallback failed");
+ }
+ }
} catch (IllegalArgumentException e) {
// Already unregistered in onStop() worker thread runnable.
}
@@ -440,31 +502,33 @@ public class BaseWifiTracker implements LifecycleObserver {
}
/**
- * Handle receiving the WifiManager.RSSI_CHANGED_ACTION broadcast
+ * Handle link property changes for the given network.
*/
@WorkerThread
- protected void handleRssiChangedAction() {
+ protected void handleLinkPropertiesChanged(
+ @NonNull Network network, @Nullable LinkProperties linkProperties) {
// Do nothing.
}
/**
- * Handle link property changes for the current connected Wifi network.
+ * Handle network capability changes for the current connected Wifi network.
*/
@WorkerThread
- protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
+ protected void handleNetworkCapabilitiesChanged(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
// Do nothing.
}
/**
- * Handle network capability changes for the current connected Wifi network.
+ * Handle the loss of a network.
*/
@WorkerThread
- protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
+ protected void handleNetworkLost(@NonNull Network network) {
// Do nothing.
}
/**
- * Handle network capability changes for the current connected Wifi network.
+ * Handle receiving a connectivity report.
*/
@WorkerThread
protected void handleConnectivityReportAvailable(
@@ -473,11 +537,19 @@ public class BaseWifiTracker implements LifecycleObserver {
}
/**
- * Handle when the default route changes. Whether Wifi is the default route is stored in
- * mIsWifiDefaultRoute.
+ * Handle default network capabilities changed.
+ */
+ @WorkerThread
+ protected void handleDefaultNetworkCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ // Do nothing.
+ }
+
+ /**
+ * Handle default network loss.
*/
@WorkerThread
- protected void handleDefaultRouteChanged() {
+ protected void handleDefaultNetworkLost() {
// Do nothing.
}
@@ -490,52 +562,265 @@ public class BaseWifiTracker implements LifecycleObserver {
}
/**
- * Scanner to handle starting scans every SCAN_INTERVAL_MILLIS
+ * Handle updates to the list of tether networks from SharedConnectivityManager.
+ */
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleHotspotNetworksUpdated(List<HotspotNetwork> networks) {
+ // Do nothing.
+ }
+
+ /**
+ * Handle updates to the list of known networks from SharedConnectivityManager.
+ */
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleKnownNetworksUpdated(List<KnownNetwork> networks) {
+ // Do nothing.
+ }
+
+ /**
+ * Handle changes to the shared connectivity settings from SharedConnectivityManager.
+ */
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleSharedConnectivitySettingsChanged(
+ @NonNull SharedConnectivitySettingsState state) {
+ // Do nothing.
+ }
+
+ /**
+ * Handle changes to the shared connectivity settings from SharedConnectivityManager.
+ */
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleHotspotNetworkConnectionStatusChanged(
+ @NonNull HotspotNetworkConnectionStatus status) {
+ // Do nothing.
+ }
+
+ /**
+ * Handle changes to the shared connectivity settings from SharedConnectivityManager.
+ */
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleKnownNetworkConnectionStatusChanged(
+ @NonNull KnownNetworkConnectionStatus status) {
+ // Do nothing.
+ }
+
+ /**
+ * Handle service connected callback from SharedConnectivityManager.
+ */
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleServiceConnected() {
+ // Do nothing.
+ }
+
+ /**
+ * Handle service disconnected callback from SharedConnectivityManager.
+ */
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleServiceDisconnected() {
+ // Do nothing.
+ }
+
+ /**
+ * Handle register callback failed callback from SharedConnectivityManager.
+ */
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleRegisterCallbackFailed(Exception exception) {
+ // Do nothing.
+ }
+
+ /**
+ * Helper class to handle starting scans every SCAN_INTERVAL_MILLIS.
+ *
+ * Scanning is only done when the activity is in the Started state and Wi-Fi is enabled.
*/
private class Scanner extends Handler {
- private static final int SCAN_RETRY_TIMES = 3;
+ private boolean mIsStartedState = false;
+ private boolean mIsWifiEnabled = false;
+ private final WifiScanner.ScanListener mFirstScanListener = new WifiScanner.ScanListener() {
+ @Override
+ @MainThread
+ public void onPeriodChanged(int periodInMs) {
+ // No-op.
+ }
+
+ @Override
+ @MainThread
+ public void onResults(WifiScanner.ScanData[] results) {
+ mWorkerHandler.post(() -> {
+ if (!shouldScan()) {
+ return;
+ }
+ if (isVerboseLoggingEnabled()) {
+ Log.v(mTag, "Received scan results from first scan request.");
+ }
+ List<ScanResult> scanResults = new ArrayList<>();
+ if (results != null) {
+ for (WifiScanner.ScanData scanData : results) {
+ scanResults.addAll(List.of(scanData.getResults()));
+ }
+ }
+ // Fake a SCAN_RESULTS_AVAILABLE_ACTION. The results should already be populated
+ // in mScanResultUpdater, which is the source of truth for the child classes.
+ mScanResultUpdater.update(scanResults);
+ handleScanResultsAvailableAction(
+ new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
+ .putExtra(WifiManager.EXTRA_RESULTS_UPDATED, true));
+ // Now start scanning via WifiManager.startScan().
+ scanLoop();
+ });
+ }
+
+ @Override
+ @MainThread
+ public void onFullResult(ScanResult fullScanResult) {
+ // No-op.
+ }
+
+ @Override
+ @MainThread
+ public void onSuccess() {
+ // No-op.
+ }
- private int mRetry = 0;
- private boolean mIsActive;
+ @Override
+ @MainThread
+ public void onFailure(int reason, String description) {
+ mWorkerHandler.post(() -> {
+ if (!mIsWifiEnabled) {
+ return;
+ }
+ Log.e(mTag, "Failed to scan! Reason: " + reason + ", ");
+ // First scan failed, start scanning normally anyway.
+ scanLoop();
+ });
+ }
+ };
private Scanner(Looper looper) {
super(looper);
}
- private void start() {
- if (!mIsActive) {
- mIsActive = true;
- if (isVerboseLoggingEnabled()) {
- Log.v(mTag, "Scanner start");
+ /**
+ * Called when the activity enters the Started state.
+ * When this happens, evaluate if we need to start scanning.
+ */
+ @MainThread
+ private void onStart() {
+ mIsStartedState = true;
+ mWorkerHandler.post(this::possiblyStartScanning);
+ }
+
+ /**
+ * Called when the activity exits the Started state.
+ * When this happens, stop scanning.
+ */
+ @MainThread
+ private void onStop() {
+ mIsStartedState = false;
+ mWorkerHandler.post(this::stopScanning);
+ }
+
+ /**
+ * Called whenever the Wi-Fi state changes. If the new state differs from the old state,
+ * then re-evaluate whether we need to start or stop scanning.
+ * @param enabled Whether Wi-Fi is enabled or not.
+ */
+ @WorkerThread
+ private void onWifiStateChanged(boolean enabled) {
+ boolean oldEnabled = mIsWifiEnabled;
+ mIsWifiEnabled = enabled;
+ if (mIsWifiEnabled != oldEnabled) {
+ if (mIsWifiEnabled) {
+ possiblyStartScanning();
+ } else {
+ stopScanning();
}
- postScan();
}
}
- private void stop() {
- mIsActive = false;
- if (isVerboseLoggingEnabled()) {
- Log.v(mTag, "Scanner stop");
+ /**
+ * Returns true if we should be scanning and false if not.
+ * Scanning should only happen when Wi-Fi is enabled and the activity is started.
+ */
+ private boolean shouldScan() {
+ return mIsWifiEnabled && mIsStartedState;
+ }
+
+ @WorkerThread
+ private void possiblyStartScanning() {
+ if (!shouldScan()) {
+ return;
}
- mRetry = 0;
+ Log.i(mTag, "Scanning started");
+ if (BuildCompat.isAtLeastU()) {
+ // Start off with a fast scan of 2.4GHz, 5GHz, and 6GHz RNR using WifiScanner.
+ // After this is done, fall back to WifiManager.startScan() to get the rest of
+ // the bands and hidden networks.
+ // TODO(b/274177966): Move to using WifiScanner exclusively once we have
+ // permission to use ScanSettings.hiddenNetworks.
+ WifiScanner.ScanSettings scanSettings = new WifiScanner.ScanSettings();
+ scanSettings.band = WifiScanner.WIFI_BAND_BOTH;
+ scanSettings.setRnrSetting(WifiScanner.WIFI_RNR_ENABLED);
+ WifiScanner wifiScanner = mContext.getSystemService(WifiScanner.class);
+ if (wifiScanner != null) {
+ wifiScanner.stopScan(mFirstScanListener);
+ if (isVerboseLoggingEnabled()) {
+ Log.v(mTag, "Issuing scan request from WifiScanner");
+ }
+ wifiScanner.startScan(scanSettings, mFirstScanListener);
+ return;
+ } else {
+ Log.e(mTag, "Failed to retrieve WifiScanner!");
+ }
+ }
+ scanLoop();
+ }
+
+ @WorkerThread
+ private void stopScanning() {
+ Log.i(mTag, "Scanning stopped");
removeCallbacksAndMessages(null);
}
- private void postScan() {
- if (mWifiManager.startScan()) {
- mRetry = 0;
- } else if (++mRetry >= SCAN_RETRY_TIMES) {
- // TODO(b/70983952): See if toast is needed here
- if (isVerboseLoggingEnabled()) {
- Log.v(mTag, "Scanner failed to start scan " + mRetry + " times!");
- }
- mRetry = 0;
+ @WorkerThread
+ private void scanLoop() {
+ if (!shouldScan()) {
+ Log.wtf(mTag, "Scan loop called even though we shouldn't be scanning!"
+ + " mIsWifiEnabled=" + mIsWifiEnabled
+ + " mIsStartedState=" + mIsStartedState);
+ return;
+ }
+ if (!isAppVisible()) {
+ Log.wtf(mTag, "Scan loop called even though app isn't visible anymore!"
+ + " mIsWifiEnabled=" + mIsWifiEnabled
+ + " mIsStartedState=" + mIsStartedState);
return;
}
- postDelayed(this::postScan, mScanIntervalMillis);
+ if (isVerboseLoggingEnabled()) {
+ Log.v(mTag, "Issuing scan request from WifiManager");
+ }
+ // Remove any pending scanLoops in case possiblyStartScanning was called more than once.
+ removeCallbacksAndMessages(null);
+ mWifiManager.startScan();
+ postDelayed(this::scanLoop, mScanIntervalMillis);
}
}
+ private boolean isAppVisible() {
+ ActivityManager.RunningAppProcessInfo processInfo =
+ new ActivityManager.RunningAppProcessInfo();
+ ActivityManager.getMyMemoryState(processInfo);
+ return processInfo.importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+ }
+
/**
* Posts onWifiStateChanged callback on the main thread.
*/
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/HotspotNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/HotspotNetworkDetailsTracker.java
new file mode 100644
index 000000000..a30dd5e7c
--- /dev/null
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/HotspotNetworkDetailsTracker.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wifitrackerlib;
+
+import static com.android.wifitrackerlib.HotspotNetworkEntry.HotspotNetworkEntryKey;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.wifi.WifiManager;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.os.Build;
+import android.os.Handler;
+import android.telephony.SubscriptionManager;
+import android.util.Log;
+
+import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
+import androidx.lifecycle.Lifecycle;
+
+import java.time.Clock;
+import java.util.List;
+
+/**
+ * Implementation of NetworkDetailsTracker that tracks a single HotspotNetworkEntry.
+ */
+@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class HotspotNetworkDetailsTracker extends NetworkDetailsTracker {
+ private static final String TAG = "HotspotNetworkDetailsTracker";
+
+ private final HotspotNetworkEntry mChosenEntry;
+
+ private HotspotNetwork mHotspotNetworkData;
+
+ public HotspotNetworkDetailsTracker(
+ @NonNull Lifecycle lifecycle,
+ @NonNull Context context,
+ @NonNull WifiManager wifiManager,
+ @NonNull ConnectivityManager connectivityManager,
+ @NonNull Handler mainHandler,
+ @NonNull Handler workerHandler,
+ @NonNull Clock clock,
+ long maxScanAgeMillis,
+ long scanIntervalMillis,
+ String key) {
+ this(new WifiTrackerInjector(context), lifecycle, context, wifiManager, connectivityManager,
+ mainHandler, workerHandler, clock, maxScanAgeMillis, scanIntervalMillis, key);
+ }
+
+ @VisibleForTesting
+ HotspotNetworkDetailsTracker(
+ @NonNull WifiTrackerInjector injector,
+ @NonNull Lifecycle lifecycle,
+ @NonNull Context context,
+ @NonNull WifiManager wifiManager,
+ @NonNull ConnectivityManager connectivityManager,
+ @NonNull Handler mainHandler,
+ @NonNull Handler workerHandler,
+ @NonNull Clock clock,
+ long maxScanAgeMillis,
+ long scanIntervalMillis,
+ String key) {
+ super(injector, lifecycle, context, wifiManager, connectivityManager,
+ mainHandler, workerHandler, clock, maxScanAgeMillis, scanIntervalMillis, TAG);
+ Log.v(TAG, "key: " + key);
+ HotspotNetworkEntryKey entryKey = new HotspotNetworkEntryKey(key);
+ if (entryKey.isVirtualEntry()) {
+ Log.e(TAG, "Network details not relevant for virtual entry");
+ }
+ mChosenEntry = new HotspotNetworkEntry(mInjector, mContext, mMainHandler, mWifiManager,
+ mSharedConnectivityManager, entryKey);
+ // It is safe to call updateStartInfo() in the main thread here since onStart() won't have
+ // a chance to post handleOnStart() on the worker thread until the main thread finishes
+ // calling this constructor.
+ updateStartInfo();
+ Log.v(TAG, "mChosenEntry: " + mChosenEntry);
+ }
+
+ @AnyThread
+ @Override
+ @NonNull
+ public WifiEntry getWifiEntry() {
+ return mChosenEntry;
+ }
+
+ @WorkerThread
+ @Override
+ protected void handleOnStart() {
+ updateStartInfo();
+ }
+
+ @WorkerThread
+ @Override
+ protected void handleServiceConnected() {
+ if (mEnableSharedConnectivityFeature && mSharedConnectivityManager != null) {
+ mHotspotNetworkData = mSharedConnectivityManager.getHotspotNetworks().stream().filter(
+ network -> network.getDeviceId() == mChosenEntry.getHotspotNetworkEntryKey()
+ .getDeviceId()).findFirst().orElse(null);
+ }
+ if (mHotspotNetworkData == null) {
+ throw new IllegalArgumentException(
+ "Cannot find data for given HotspotNetworkEntry key!");
+ }
+ mChosenEntry.updateHotspotNetworkData(mHotspotNetworkData);
+ }
+
+ @WorkerThread
+ @Override
+ protected void handleHotspotNetworksUpdated(List<HotspotNetwork> networks) {
+ if (mEnableSharedConnectivityFeature) {
+ mHotspotNetworkData = networks.stream().filter(network -> network.getDeviceId()
+ == mChosenEntry.getHotspotNetworkEntryKey().getDeviceId()).findFirst().orElse(
+ null);
+ }
+ if (mHotspotNetworkData == null) {
+ throw new IllegalArgumentException(
+ "Cannot find data for given HotspotNetworkEntry key!");
+ }
+ mChosenEntry.updateHotspotNetworkData(mHotspotNetworkData);
+ }
+
+ @WorkerThread
+ private void updateStartInfo() {
+ handleDefaultSubscriptionChanged(SubscriptionManager.getDefaultDataSubscriptionId());
+ Network currentNetwork = mWifiManager.getCurrentNetwork();
+ if (currentNetwork == null) return;
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(currentNetwork);
+ if (networkCapabilities != null) {
+ // getNetworkCapabilities(Network) obfuscates location info such as SSID and
+ // networkId, so we need to set the WifiInfo directly from WifiManager.
+ handleNetworkCapabilitiesChanged(currentNetwork,
+ new NetworkCapabilities.Builder(networkCapabilities)
+ .setTransportInfo(mWifiManager.getConnectionInfo())
+ .build());
+ }
+ LinkProperties linkProperties = mConnectivityManager.getLinkProperties(currentNetwork);
+ if (linkProperties != null) {
+ handleLinkPropertiesChanged(currentNetwork, linkProperties);
+ }
+ }
+}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/HotspotNetworkEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/HotspotNetworkEntry.java
new file mode 100644
index 000000000..0495fef9c
--- /dev/null
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/HotspotNetworkEntry.java
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wifitrackerlib;
+
+import static android.os.Build.VERSION_CODES;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
+import android.os.Handler;
+import android.text.BidiFormatter;
+import android.util.Log;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * WifiEntry representation of a Hotspot Network provided via {@link SharedConnectivityManager}.
+ */
+@TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class HotspotNetworkEntry extends WifiEntry {
+ static final String TAG = "HotspotNetworkEntry";
+ public static final String KEY_PREFIX = "HotspotNetworkEntry:";
+
+ @NonNull private final WifiTrackerInjector mInjector;
+ @NonNull private final Context mContext;
+ @Nullable private final SharedConnectivityManager mSharedConnectivityManager;
+
+ @Nullable private HotspotNetwork mHotspotNetworkData;
+ @NonNull private HotspotNetworkEntryKey mKey;
+
+ private boolean mServerInitiatedConnection = false;
+
+ /**
+ * If editing this IntDef also edit the definition in:
+ * {@link android.net.wifi.sharedconnectivity.app.HotspotNetwork}
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ HotspotNetwork.NETWORK_TYPE_UNKNOWN,
+ HotspotNetwork.NETWORK_TYPE_CELLULAR,
+ HotspotNetwork.NETWORK_TYPE_WIFI,
+ HotspotNetwork.NETWORK_TYPE_ETHERNET
+ })
+ public @interface NetworkType {} // TODO(b/271868642): Add IfThisThanThat lint
+
+ /**
+ * If editing this IntDef also edit the definition in:
+ * {@link android.net.wifi.sharedconnectivity.app.NetworkProviderInfo}
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ NetworkProviderInfo.DEVICE_TYPE_UNKNOWN,
+ NetworkProviderInfo.DEVICE_TYPE_PHONE,
+ NetworkProviderInfo.DEVICE_TYPE_TABLET,
+ NetworkProviderInfo.DEVICE_TYPE_LAPTOP,
+ NetworkProviderInfo.DEVICE_TYPE_WATCH,
+ NetworkProviderInfo.DEVICE_TYPE_AUTO
+ })
+ public @interface DeviceType {} // TODO(b/271868642): Add IfThisThanThat lint
+
+ /**
+ * If editing this IntDef also edit the definition in:
+ * {@link android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus}
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN_ERROR,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_PROVISIONING_FAILED,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_UNSUPPORTED,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_NO_CELL_DATA,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT,
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED,
+ })
+ public @interface ConnectionStatus {} // TODO(b/271868642): Add IfThisThanThat lint
+
+ /**
+ * Create a HotspotNetworkEntry from HotspotNetwork data.
+ */
+ HotspotNetworkEntry(
+ @NonNull WifiTrackerInjector injector,
+ @NonNull Context context, @NonNull Handler callbackHandler,
+ @NonNull WifiManager wifiManager,
+ @Nullable SharedConnectivityManager sharedConnectivityManager,
+ @NonNull HotspotNetwork hotspotNetworkData) {
+ super(callbackHandler, wifiManager, false /*forSavedNetworksPage*/);
+ mInjector = injector;
+ mContext = context;
+ mSharedConnectivityManager = sharedConnectivityManager;
+ mHotspotNetworkData = hotspotNetworkData;
+ mKey = new HotspotNetworkEntryKey(hotspotNetworkData);
+ }
+
+ /**
+ * Create a HotspotNetworkEntry from HotspotNetworkEntryKey.
+ */
+ HotspotNetworkEntry(
+ @NonNull WifiTrackerInjector injector,
+ @NonNull Context context, @NonNull Handler callbackHandler,
+ @NonNull WifiManager wifiManager,
+ @Nullable SharedConnectivityManager sharedConnectivityManager,
+ @NonNull HotspotNetworkEntryKey key) {
+ super(callbackHandler, wifiManager, false /*forSavedNetworksPage*/);
+ mInjector = injector;
+ mContext = context;
+ mSharedConnectivityManager = sharedConnectivityManager;
+ mHotspotNetworkData = null;
+ mKey = key;
+ }
+
+ @Override
+ public String getKey() {
+ return mKey.toString();
+ }
+
+ public HotspotNetworkEntryKey getHotspotNetworkEntryKey() {
+ return mKey;
+ }
+
+ /**
+ * Updates the hotspot data for this entry. Creates a new key when called.
+ *
+ * @param hotspotNetworkData An updated data set from SharedConnectivityService.
+ */
+ @WorkerThread
+ protected synchronized void updateHotspotNetworkData(
+ @NonNull HotspotNetwork hotspotNetworkData) {
+ mHotspotNetworkData = hotspotNetworkData;
+ mKey = new HotspotNetworkEntryKey(hotspotNetworkData);
+ notifyOnUpdated();
+ }
+
+ @WorkerThread
+ protected synchronized boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo) {
+ if (mKey.isVirtualEntry()) {
+ return false;
+ }
+ return Objects.equals(mKey.getBssid(), wifiInfo.getBSSID());
+ }
+
+ @Override
+ public String getTitle() {
+ if (mHotspotNetworkData == null) {
+ return "";
+ }
+ return mHotspotNetworkData.getNetworkProviderInfo().getDeviceName();
+ }
+
+ @Override
+ public String getSummary(boolean concise) {
+ if (mHotspotNetworkData == null) {
+ return "";
+ }
+ if (getConnectedState() != CONNECTED_STATE_CONNECTED && mServerInitiatedConnection) {
+ return mContext.getString(R.string.wifitrackerlib_hotspot_network_connecting);
+ }
+ return mContext.getString(R.string.wifitrackerlib_hotspot_network_summary,
+ BidiFormatter.getInstance().unicodeWrap(mHotspotNetworkData.getNetworkName()),
+ BidiFormatter.getInstance().unicodeWrap(
+ mHotspotNetworkData.getNetworkProviderInfo().getModelName()));
+ }
+
+ /**
+ * Alternate summary string to be used on Network & internet page.
+ *
+ * @return Display string.
+ */
+ public String getAlternateSummary() {
+ if (mHotspotNetworkData == null) {
+ return "";
+ }
+ return mContext.getString(R.string.wifitrackerlib_hotspot_network_alternate,
+ BidiFormatter.getInstance().unicodeWrap(mHotspotNetworkData.getNetworkName()),
+ BidiFormatter.getInstance().unicodeWrap(
+ mHotspotNetworkData.getNetworkProviderInfo().getDeviceName()));
+ }
+
+ /**
+ * Connection strength between the host device and the internet.
+ *
+ * @return Displayed connection strength in the range 0 to 4.
+ */
+ @IntRange(from = 0, to = 4)
+ public int getUpstreamConnectionStrength() {
+ if (mHotspotNetworkData == null) {
+ return 0;
+ }
+ return mHotspotNetworkData.getNetworkProviderInfo().getConnectionStrength();
+ }
+
+ /**
+ * Network type used by the host device to connect to the internet.
+ *
+ * @return NetworkType enum.
+ */
+ @NetworkType
+ public int getNetworkType() {
+ if (mHotspotNetworkData == null) {
+ return HotspotNetwork.NETWORK_TYPE_UNKNOWN;
+ }
+ return mHotspotNetworkData.getHostNetworkType();
+ }
+
+ /**
+ * Device type of the host device.
+ *
+ * @return DeviceType enum.
+ */
+ @DeviceType
+ public int getDeviceType() {
+ if (mHotspotNetworkData == null) {
+ return NetworkProviderInfo.DEVICE_TYPE_UNKNOWN;
+ }
+ return mHotspotNetworkData.getNetworkProviderInfo().getDeviceType();
+ }
+
+ /**
+ * The battery percentage of the host device.
+ */
+ @IntRange(from = 0, to = 100)
+ public int getBatteryPercentage() {
+ if (mHotspotNetworkData == null) {
+ return 0;
+ }
+ return mHotspotNetworkData.getNetworkProviderInfo().getBatteryPercentage();
+ }
+
+ /**
+ * If the host device is currently charging its battery.
+ */
+ public boolean isBatteryCharging() {
+ if (mHotspotNetworkData == null) {
+ return false;
+ }
+ return mHotspotNetworkData.getExtras().getBoolean("is_battery_charging", false);
+ }
+
+ @Override
+ public boolean canConnect() {
+ return getConnectedState() == CONNECTED_STATE_DISCONNECTED;
+ }
+
+ @Override
+ public void connect(@Nullable ConnectCallback callback) {
+ mConnectCallback = callback;
+ if (mSharedConnectivityManager == null) {
+ if (callback != null) {
+ mCallbackHandler.post(() -> callback.onConnectResult(
+ ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN));
+ }
+ return;
+ }
+ mSharedConnectivityManager.connectHotspotNetwork(mHotspotNetworkData);
+ }
+
+ @Override
+ public boolean canDisconnect() {
+ return getConnectedState() != CONNECTED_STATE_DISCONNECTED;
+ }
+
+ @Override
+ public void disconnect(@Nullable DisconnectCallback callback) {
+ mDisconnectCallback = callback;
+ if (mSharedConnectivityManager == null) {
+ if (callback != null) {
+ mCallbackHandler.post(() -> callback.onDisconnectResult(
+ DisconnectCallback.DISCONNECT_STATUS_FAILURE_UNKNOWN));
+ }
+ return;
+ }
+ mSharedConnectivityManager.disconnectHotspotNetwork(mHotspotNetworkData);
+ }
+
+ @Nullable
+ public HotspotNetwork getHotspotNetworkData() {
+ return mHotspotNetworkData;
+ }
+
+ /**
+ * Trigger ConnectCallback with data from SharedConnectivityService.
+ * @param status HotspotNetworkConnectionStatus#ConnectionStatus enum.
+ */
+ public void onConnectionStatusChanged(@ConnectionStatus int status) {
+ if (mConnectCallback == null) return;
+ switch (status) {
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT:
+ mServerInitiatedConnection = true;
+ notifyOnUpdated();
+ break;
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN_ERROR:
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_PROVISIONING_FAILED:
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT:
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_UNSUPPORTED:
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_NO_CELL_DATA:
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED:
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT:
+ case HotspotNetworkConnectionStatus.CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED:
+ mCallbackHandler.post(() -> mConnectCallback.onConnectResult(
+ ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN));
+ mServerInitiatedConnection = false;
+ notifyOnUpdated();
+ break;
+ default:
+ // Do nothing
+ }
+ }
+
+ static class HotspotNetworkEntryKey {
+ private static final String KEY_IS_VIRTUAL_ENTRY_KEY = "IS_VIRTUAL_ENTRY_KEY";
+ private static final String KEY_DEVICE_ID_KEY = "DEVICE_ID_KEY";
+ private static final String KEY_BSSID_KEY = "BSSID_KEY";
+ private static final String KEY_SCAN_RESULT_KEY = "SCAN_RESULT_KEY";
+
+ private boolean mIsVirtualEntry;
+ private long mDeviceId;
+ @Nullable
+ private String mBssid;
+ @Nullable
+ private StandardWifiEntry.ScanResultKey mScanResultKey;
+
+ /**
+ * Creates a HotspotNetworkEntryKey based on a {@link HotspotNetwork} parcelable object.
+ *
+ * @param hotspotNetworkData A {@link HotspotNetwork} object from SharedConnectivityService.
+ */
+ HotspotNetworkEntryKey(@NonNull HotspotNetwork hotspotNetworkData) {
+ mDeviceId = hotspotNetworkData.getDeviceId();
+ if (hotspotNetworkData.getHotspotSsid() == null
+ || (hotspotNetworkData.getHotspotBssid() == null)
+ || (hotspotNetworkData.getHotspotSecurityTypes() == null)) {
+ mIsVirtualEntry = true;
+ mBssid = null;
+ mScanResultKey = null;
+ } else {
+ mIsVirtualEntry = false;
+ mBssid = hotspotNetworkData.getHotspotBssid();
+ mScanResultKey = new StandardWifiEntry.ScanResultKey(
+ hotspotNetworkData.getHotspotSsid(),
+ new ArrayList<>(hotspotNetworkData.getHotspotSecurityTypes()));
+ }
+ }
+
+ /**
+ * Creates a HotspotNetworkEntryKey from its String representation.
+ */
+ HotspotNetworkEntryKey(@NonNull String string) {
+ mScanResultKey = null;
+ if (!string.startsWith(KEY_PREFIX)) {
+ Log.e(TAG, "String key does not start with key prefix!");
+ return;
+ }
+ try {
+ final JSONObject keyJson = new JSONObject(
+ string.substring(KEY_PREFIX.length()));
+ if (keyJson.has(KEY_IS_VIRTUAL_ENTRY_KEY)) {
+ mIsVirtualEntry = keyJson.getBoolean(KEY_IS_VIRTUAL_ENTRY_KEY);
+ }
+ if (keyJson.has(KEY_DEVICE_ID_KEY)) {
+ mDeviceId = keyJson.getLong(KEY_DEVICE_ID_KEY);
+ }
+ if (keyJson.has(KEY_BSSID_KEY)) {
+ mBssid = keyJson.getString(KEY_BSSID_KEY);
+ }
+ if (keyJson.has(KEY_SCAN_RESULT_KEY)) {
+ mScanResultKey = new StandardWifiEntry.ScanResultKey(keyJson.getString(
+ KEY_SCAN_RESULT_KEY));
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "JSONException while converting HotspotNetworkEntryKey to string: " + e);
+ }
+ }
+
+ /**
+ * Returns the JSON String representation of this HotspotNetworkEntryKey.
+ */
+ @Override
+ public String toString() {
+ final JSONObject keyJson = new JSONObject();
+ try {
+ keyJson.put(KEY_IS_VIRTUAL_ENTRY_KEY, mIsVirtualEntry);
+ keyJson.put(KEY_DEVICE_ID_KEY, mDeviceId);
+ if (mBssid != null) {
+ keyJson.put(KEY_BSSID_KEY, mBssid);
+ }
+ if (mScanResultKey != null) {
+ keyJson.put(KEY_SCAN_RESULT_KEY, mScanResultKey.toString());
+ }
+ } catch (JSONException e) {
+ Log.wtf(TAG,
+ "JSONException while converting HotspotNetworkEntryKey to string: " + e);
+ }
+ return KEY_PREFIX + keyJson.toString();
+ }
+
+ public boolean isVirtualEntry() {
+ return mIsVirtualEntry;
+ }
+
+ public long getDeviceId() {
+ return mDeviceId;
+ }
+
+ /**
+ * Returns the BSSID of this HotspotNetworkEntryKey to match against wifiInfo
+ */
+ @Nullable
+ String getBssid() {
+ return mBssid;
+ }
+
+ /**
+ * Returns the ScanResultKey of this HotspotNetworkEntryKey to match against ScanResults
+ */
+ @Nullable
+ StandardWifiEntry.ScanResultKey getScanResultKey() {
+ return mScanResultKey;
+ }
+ }
+}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/KnownNetworkEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/KnownNetworkEntry.java
new file mode 100644
index 000000000..f163ee300
--- /dev/null
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/KnownNetworkEntry.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wifitrackerlib;
+
+import static android.os.Build.VERSION_CODES;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
+import android.os.Handler;
+import android.text.BidiFormatter;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * WifiEntry representation of a Known Network provided via {@link SharedConnectivityManager}.
+ */
+@TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class KnownNetworkEntry extends StandardWifiEntry{
+ static final String TAG = "KnownNetworkEntry";
+
+ @Nullable private final SharedConnectivityManager mSharedConnectivityManager;
+ @NonNull private final KnownNetwork mKnownNetworkData;
+
+ /**
+ * If editing this IntDef also edit the definition in:
+ * {@link android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus}
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ KnownNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN,
+ KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED,
+ KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED,
+ })
+ public @interface ConnectionStatus {} // TODO(b/271868642): Add IfThisThanThat lint
+
+ KnownNetworkEntry(
+ @NonNull WifiTrackerInjector injector, @NonNull Context context,
+ @NonNull Handler callbackHandler, @NonNull StandardWifiEntryKey key,
+ @NonNull WifiManager wifiManager,
+ @Nullable SharedConnectivityManager sharedConnectivityManager,
+ @NonNull KnownNetwork knownNetworkData) {
+ super(injector, context, callbackHandler, key, wifiManager,
+ false /* forSavedNetworksPage */);
+ mSharedConnectivityManager = sharedConnectivityManager;
+ mKnownNetworkData = knownNetworkData;
+ }
+
+ KnownNetworkEntry(
+ @NonNull WifiTrackerInjector injector, @NonNull Context context,
+ @NonNull Handler callbackHandler, @NonNull StandardWifiEntryKey key,
+ @Nullable List<WifiConfiguration> configs, @Nullable List<ScanResult> scanResults,
+ @NonNull WifiManager wifiManager,
+ @Nullable SharedConnectivityManager sharedConnectivityManager,
+ @NonNull KnownNetwork knownNetworkData) throws IllegalArgumentException {
+ super(injector, context, callbackHandler, key, configs, scanResults, wifiManager,
+ false /* forSavedNetworksPage */);
+ mSharedConnectivityManager = sharedConnectivityManager;
+ mKnownNetworkData = knownNetworkData;
+ }
+
+ @Override
+ public synchronized String getSummary(boolean concise) {
+ return mContext.getString(R.string.wifitrackerlib_known_network_summary,
+ BidiFormatter.getInstance().unicodeWrap(
+ mKnownNetworkData.getNetworkProviderInfo().getDeviceName()));
+ }
+
+ @Override
+ public synchronized void connect(@Nullable ConnectCallback callback) {
+ mConnectCallback = callback;
+ if (mSharedConnectivityManager == null) {
+ if (callback != null) {
+ mCallbackHandler.post(() -> callback.onConnectResult(
+ ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN));
+ }
+ return;
+ }
+ mSharedConnectivityManager.connectKnownNetwork(mKnownNetworkData);
+ }
+
+ @Override
+ public synchronized boolean isSaved() {
+ return false;
+ }
+
+ @Override
+ public synchronized boolean isSuggestion() {
+ return false;
+ }
+
+ @WorkerThread
+ protected synchronized boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo) {
+ if (wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) {
+ return false;
+ }
+ return Objects.equals(getStandardWifiEntryKey().getScanResultKey(),
+ ssidAndSecurityTypeToStandardWifiEntryKey(WifiInfo.sanitizeSsid(wifiInfo.getSSID()),
+ wifiInfo.getCurrentSecurityType()).getScanResultKey());
+ }
+
+ /**
+ * Trigger ConnectCallback with data from SharedConnectivityService.
+ * @param status KnownNetworkConnectionStatus#ConnectionStatus enum.
+ */
+ public void onConnectionStatusChanged(@ConnectionStatus int status) {
+ if (status == KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED
+ && mConnectCallback != null) {
+ mCallbackHandler.post(() -> mConnectCallback.onConnectResult(
+ ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN));
+ }
+ }
+}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/MergedCarrierEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/MergedCarrierEntry.java
index 9d0e15262..413a1ee2d 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/MergedCarrierEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/MergedCarrierEntry.java
@@ -22,7 +22,6 @@ import static android.net.wifi.WifiInfo.sanitizeSsid;
import static com.android.wifitrackerlib.Utils.getVerboseLoggingDescription;
import android.content.Context;
-import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -153,8 +152,7 @@ public class MergedCarrierEntry extends WifiEntry {
}
@WorkerThread
- protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo,
- @NonNull NetworkInfo networkInfo) {
+ protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo) {
return wifiInfo.isCarrierMerged() && mSubscriptionId == wifiInfo.getSubscriptionId();
}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java
index 47528cd43..5ed599e33 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java
@@ -16,8 +16,6 @@
package com.android.wifitrackerlib;
-import static androidx.core.util.Preconditions.checkNotNull;
-
import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
import android.content.Context;
@@ -25,8 +23,10 @@ import android.content.Intent;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
+import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -105,13 +105,15 @@ public abstract class NetworkDetailsTracker extends BaseWifiTracker {
return new PasspointNetworkDetailsTracker(injector, lifecycle, context, wifiManager,
connectivityManager, mainHandler, workerHandler, clock,
maxScanAgeMillis, scanIntervalMillis, key);
+ } else if (key.startsWith(HotspotNetworkEntry.KEY_PREFIX)) {
+ return new HotspotNetworkDetailsTracker(injector, lifecycle, context, wifiManager,
+ connectivityManager, mainHandler, workerHandler, clock,
+ maxScanAgeMillis, scanIntervalMillis, key);
} else {
throw new IllegalArgumentException("Key does not contain valid key prefix!");
}
}
- protected NetworkInfo mCurrentNetworkInfo;
-
/**
* Abstract constructor for NetworkDetailsTracker.
* Clients must use {@link NetworkDetailsTracker#createNetworkDetailsTracker} for creating
@@ -137,54 +139,55 @@ public abstract class NetworkDetailsTracker extends BaseWifiTracker {
@WorkerThread
@Override
protected void handleNetworkStateChangedAction(@NonNull Intent intent) {
- checkNotNull(intent, "Intent cannot be null!");
- mCurrentNetworkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- getWifiEntry().updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
+ WifiInfo primaryWifiInfo = mWifiManager.getConnectionInfo();
+ NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ if (primaryWifiInfo == null || networkInfo == null) {
+ return;
+ }
+ getWifiEntry().onPrimaryWifiInfoChanged(primaryWifiInfo, networkInfo);
}
@WorkerThread
@Override
- protected void handleRssiChangedAction() {
- getWifiEntry().updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
+ protected void handleLinkPropertiesChanged(
+ @NonNull Network network, @Nullable LinkProperties linkProperties) {
+ final WifiEntry chosenEntry = getWifiEntry();
+ if (chosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
+ chosenEntry.updateLinkProperties(network, linkProperties);
+ }
}
@WorkerThread
@Override
- protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
- final WifiEntry chosenEntry = getWifiEntry();
- if (chosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- chosenEntry.updateLinkProperties(linkProperties);
- }
+ protected void handleNetworkCapabilitiesChanged(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ getWifiEntry().onNetworkCapabilitiesChanged(network, capabilities);
}
@WorkerThread
@Override
- protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
- final WifiEntry chosenEntry = getWifiEntry();
- if (chosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- chosenEntry.updateNetworkCapabilities(capabilities);
- chosenEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
- }
+ protected void handleNetworkLost(@NonNull Network network) {
+ getWifiEntry().onNetworkLost(network);
}
@WorkerThread
@Override
- protected void handleConnectivityReportAvailable(
- @NonNull ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport) {
- final WifiEntry chosenEntry = getWifiEntry();
- if (chosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- chosenEntry.updateConnectivityReport(connectivityReport);
- }
+ protected void handleDefaultNetworkCapabilitiesChanged(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ getWifiEntry().onDefaultNetworkCapabilitiesChanged(network, capabilities);
}
@WorkerThread
@Override
- protected void handleDefaultRouteChanged() {
- final WifiEntry chosenEntry = getWifiEntry();
- if (chosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- chosenEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
- chosenEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
- }
+ protected void handleDefaultNetworkLost() {
+ getWifiEntry().onDefaultNetworkLost();
+ }
+
+ @WorkerThread
+ @Override
+ protected void handleConnectivityReportAvailable(
+ @NonNull ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport) {
+ getWifiEntry().updateConnectivityReport(connectivityReport);
}
/**
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java
index 11cbfb77f..efeb19ad0 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkRequestEntry.java
@@ -45,17 +45,17 @@ public class NetworkRequestEntry extends StandardWifiEntry {
}
@Override
- public boolean isMetered() {
+ public synchronized boolean isMetered() {
return false;
}
@Override
- public boolean isSaved() {
+ public synchronized boolean isSaved() {
return false;
}
@Override
- public boolean isSuggestion() {
+ public synchronized boolean isSuggestion() {
return false;
}
@@ -65,17 +65,17 @@ public class NetworkRequestEntry extends StandardWifiEntry {
}
@Override
- public WifiConfiguration getWifiConfiguration() {
+ public synchronized WifiConfiguration getWifiConfiguration() {
return null;
}
@Override
- public boolean canConnect() {
+ public synchronized boolean canConnect() {
return false;
}
@Override
- public void connect(@Nullable ConnectCallback callback) {
+ public synchronized void connect(@Nullable ConnectCallback callback) {
return;
}
@@ -85,23 +85,23 @@ public class NetworkRequestEntry extends StandardWifiEntry {
}
@Override
- public void forget(@Nullable ForgetCallback callback) {
+ public synchronized void forget(@Nullable ForgetCallback callback) {
return;
}
@Override
- public boolean canShare() {
+ public synchronized boolean canShare() {
return false;
}
@Override
- public boolean canEasyConnect() {
+ public synchronized boolean canEasyConnect() {
return false;
}
@Override
@MeteredChoice
- public int getMeteredChoice() {
+ public synchronized int getMeteredChoice() {
return METERED_CHOICE_AUTO;
}
@@ -111,7 +111,7 @@ public class NetworkRequestEntry extends StandardWifiEntry {
}
@Override
- public void setMeteredChoice(int meteredChoice) {
+ public synchronized void setMeteredChoice(int meteredChoice) {
return;
}
@@ -122,17 +122,17 @@ public class NetworkRequestEntry extends StandardWifiEntry {
@Override
@Privacy
- public int getPrivacy() {
+ public synchronized int getPrivacy() {
return PRIVACY_RANDOMIZED_MAC;
}
@Override
- public void setPrivacy(int privacy) {
+ public synchronized void setPrivacy(int privacy) {
return;
}
@Override
- public boolean isAutoJoinEnabled() {
+ public synchronized boolean isAutoJoinEnabled() {
return true;
}
@@ -142,7 +142,7 @@ public class NetworkRequestEntry extends StandardWifiEntry {
}
@Override
- public void setAutoJoinEnabled(boolean enabled) {
+ public synchronized void setAutoJoinEnabled(boolean enabled) {
return;
}
}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NonSdkApiWrapper.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NonSdkApiWrapper.java
index 0d9cb4302..0a71bcbe8 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NonSdkApiWrapper.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NonSdkApiWrapper.java
@@ -25,7 +25,6 @@ import android.net.NetworkCapabilities;
import android.net.TransportInfo;
import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
-import android.os.Handler;
import android.os.UserManager;
import android.text.Annotation;
import android.text.SpannableString;
@@ -48,6 +47,10 @@ import com.android.settingslib.HelpUtils;
* replaces this class with the version found in WifiTrackerLib/sdk_src/../NonSdkApiWrapper.java.
*/
class NonSdkApiWrapper {
+ private NonSdkApiWrapper() {
+ // Empty constructor to make this class non-instantiable.
+ }
+
/**
* Starts the System captive portal app.
*/
@@ -89,13 +92,14 @@ class NonSdkApiWrapper {
}
/**
- * Returns whether or not the network capabilities is determined to be VCN over Wi-Fi or not.
+ * Tries to get WifiInfo from network capabilities if it is VCN-over-Wifi.
*/
- static boolean isVcnOverWifi(@NonNull NetworkCapabilities networkCapabilities) {
+ static WifiInfo getVcnWifiInfo(@NonNull NetworkCapabilities networkCapabilities) {
TransportInfo transportInfo = networkCapabilities.getTransportInfo();
- return transportInfo != null
- && transportInfo instanceof VcnTransportInfo
- && ((VcnTransportInfo) transportInfo).getWifiInfo() != null;
+ if (transportInfo instanceof VcnTransportInfo) {
+ return ((VcnTransportInfo) transportInfo).getWifiInfo();
+ }
+ return null;
}
/**
@@ -106,20 +110,18 @@ class NonSdkApiWrapper {
}
/**
- * Registers the default network callback.
+ * Returns true if the WifiInfo is for the primary network, false otherwise.
*/
- static void registerSystemDefaultNetworkCallback(
- @NonNull ConnectivityManager connectivityManager,
- @NonNull ConnectivityManager.NetworkCallback callback,
- @NonNull Handler handler) {
- connectivityManager.registerSystemDefaultNetworkCallback(callback, handler);
+ static boolean isPrimary(@NonNull WifiInfo wifiInfo) {
+ return wifiInfo.isPrimary();
}
/**
- * Returns true if the WifiInfo is for the primary network, false otherwise.
+ * Returns true if the NetworkCapabilities is OEM_PAID or OEM_PRIVATE
*/
- static boolean isPrimary(@NonNull WifiInfo wifiInfo) {
- return wifiInfo.isPrimary();
+ static boolean isOemCapabilities(@NonNull NetworkCapabilities capabilities) {
+ return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)
+ || capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE);
}
/**
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
index 7d8361b85..7d8ad4edb 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
@@ -22,7 +22,6 @@ import static com.android.wifitrackerlib.Utils.getBestScanResultByLevel;
import static com.android.wifitrackerlib.WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN;
import android.content.Context;
-import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
@@ -185,8 +184,7 @@ class OsuWifiEntry extends WifiEntry {
@WorkerThread
@Override
- protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo,
- @NonNull NetworkInfo networkInfo) {
+ protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo) {
return wifiInfo.isOsuAp() && TextUtils.equals(
wifiInfo.getPasspointProviderFriendlyName(), mOsuProvider.getFriendlyName());
}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
index db8830d81..b6be43f48 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
@@ -24,11 +24,11 @@ import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkInfo;
+import android.net.NetworkCapabilities;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
@@ -55,7 +55,6 @@ public class PasspointNetworkDetailsTracker extends NetworkDetailsTracker {
private final PasspointWifiEntry mChosenEntry;
private OsuWifiEntry mOsuWifiEntry;
- private NetworkInfo mCurrentNetworkInfo;
private WifiConfiguration mCurrentWifiConfig;
public PasspointNetworkDetailsTracker(@NonNull Lifecycle lifecycle,
@@ -159,15 +158,23 @@ public class PasspointNetworkDetailsTracker extends NetworkDetailsTracker {
private void updateStartInfo() {
conditionallyUpdateScanResults(true /* lastScanSucceeded */);
conditionallyUpdateConfig();
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- final Network currentNetwork = mWifiManager.getCurrentNetwork();
- mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
- mChosenEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
- handleNetworkCapabilitiesChanged(
- mConnectivityManager.getNetworkCapabilities(currentNetwork));
- handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
- mChosenEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
- mChosenEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+ Network currentNetwork = mWifiManager.getCurrentNetwork();
+ if (currentNetwork != null) {
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(currentNetwork);
+ if (networkCapabilities != null) {
+ // getNetworkCapabilities(Network) obfuscates location info such as SSID and
+ // networkId, so we need to set the WifiInfo directly from WifiManager.
+ handleNetworkCapabilitiesChanged(currentNetwork,
+ new NetworkCapabilities.Builder(networkCapabilities)
+ .setTransportInfo(mWifiManager.getConnectionInfo())
+ .build());
+ }
+ LinkProperties linkProperties = mConnectivityManager.getLinkProperties(currentNetwork);
+ if (linkProperties != null) {
+ handleLinkPropertiesChanged(currentNetwork, linkProperties);
+ }
+ }
}
@WorkerThread
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
index 193b8ec69..c47570061 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
@@ -34,8 +34,8 @@ import static com.android.wifitrackerlib.Utils.getVerboseLoggingDescription;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
@@ -48,10 +48,10 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -60,7 +60,6 @@ import java.util.StringJoiner;
/**
* WifiEntry representation of a subscribed Passpoint network, uniquely identified by FQDN.
*/
-@VisibleForTesting
public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntryCallback {
static final String TAG = "PasspointWifiEntry";
public static final String KEY_PREFIX = "PasspointWifiEntry:";
@@ -77,9 +76,8 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
private PasspointConfiguration mPasspointConfig;
@Nullable private WifiConfiguration mWifiConfig;
private List<Integer> mTargetSecurityTypes =
- List.of(SECURITY_TYPE_PASSPOINT_R1_R2, SECURITY_TYPE_PASSPOINT_R3);
+ Arrays.asList(SECURITY_TYPE_PASSPOINT_R1_R2, SECURITY_TYPE_PASSPOINT_R3);
- private boolean mIsRoaming = false;
private OsuWifiEntry mOsuWifiEntry;
private boolean mShouldAutoOpenCaptivePortal = false;
@@ -193,7 +191,7 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
mWifiConfig,
mNetworkCapabilities,
mIsDefaultNetwork,
- mIsLowQuality,
+ isLowQuality(),
mConnectivityReport);
break;
default:
@@ -468,6 +466,20 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
}
@Override
+ public synchronized String getBandString() {
+ if (mWifiInfo != null) {
+ return Utils.getBandString(mContext, mWifiInfo);
+ }
+ if (!mCurrentHomeScanResults.isEmpty()) {
+ return Utils.getBandString(mContext, mCurrentHomeScanResults.get(0).frequency);
+ }
+ if (!mCurrentRoamingScanResults.isEmpty()) {
+ return Utils.getBandString(mContext, mCurrentRoamingScanResults.get(0).frequency);
+ }
+ return "";
+ }
+
+ @Override
public synchronized boolean isExpired() {
if (mSubscriptionExpirationTimeInMillis <= 0) {
// Expiration time not specified.
@@ -493,7 +505,6 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
@Nullable List<ScanResult> homeScanResults,
@Nullable List<ScanResult> roamingScanResults)
throws IllegalArgumentException {
- mIsRoaming = false;
mWifiConfig = wifiConfig;
mCurrentHomeScanResults.clear();
mCurrentRoamingScanResults.clear();
@@ -505,14 +516,12 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
}
if (mWifiConfig != null) {
List<ScanResult> currentScanResults = new ArrayList<>();
- ScanResult bestScanResult = null;
if (homeScanResults != null && !homeScanResults.isEmpty()) {
currentScanResults.addAll(homeScanResults);
} else if (roamingScanResults != null && !roamingScanResults.isEmpty()) {
currentScanResults.addAll(roamingScanResults);
- mIsRoaming = true;
}
- bestScanResult = getBestScanResultByLevel(currentScanResults);
+ ScanResult bestScanResult = getBestScanResultByLevel(currentScanResults);
if (bestScanResult != null) {
mWifiConfig.SSID = "\"" + bestScanResult.SSID + "\"";
}
@@ -540,8 +549,7 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
@WorkerThread
@Override
- protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo,
- @NonNull NetworkInfo networkInfo) {
+ protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo) {
if (!wifiInfo.isPasspointAp()) {
return false;
}
@@ -552,8 +560,9 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
@WorkerThread
@Override
- synchronized void updateNetworkCapabilities(@Nullable NetworkCapabilities capabilities) {
- super.updateNetworkCapabilities(capabilities);
+ synchronized void onNetworkCapabilitiesChanged(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ super.onNetworkCapabilitiesChanged(network, capabilities);
// Auto-open an available captive portal if the user manually connected to this network.
if (canSignIn() && mShouldAutoOpenCaptivePortal) {
@@ -595,7 +604,8 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
@Override
public synchronized boolean canSignIn() {
- return mNetworkCapabilities != null
+ return mNetwork != null
+ && mNetworkCapabilities != null
&& mNetworkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
}
@@ -603,11 +613,8 @@ public class PasspointWifiEntry extends WifiEntry implements WifiEntry.WifiEntry
@Override
public void signIn(@Nullable SignInCallback callback) {
if (canSignIn()) {
- // canSignIn() implies that this WifiEntry is the currently connected network, so use
- // getCurrentNetwork() to start the captive portal app.
NonSdkApiWrapper.startCaptivePortalApp(
- mContext.getSystemService(ConnectivityManager.class),
- mWifiManager.getCurrentNetwork());
+ mContext.getSystemService(ConnectivityManager.class), mNetwork);
}
}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java
index af69094d7..cf6288a2f 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/SavedNetworkTracker.java
@@ -21,8 +21,6 @@ import static androidx.core.util.Preconditions.checkNotNull;
import static com.android.wifitrackerlib.PasspointWifiEntry.uniqueIdToPasspointWifiEntryKey;
import static com.android.wifitrackerlib.StandardWifiEntry.ScanResultKey;
import static com.android.wifitrackerlib.StandardWifiEntry.StandardWifiEntryKey;
-import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
-import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_DISCONNECTED;
import static java.util.stream.Collectors.toMap;
@@ -36,10 +34,13 @@ import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Handler;
+import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
@@ -56,7 +57,6 @@ import java.time.Clock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -86,10 +86,7 @@ public class SavedNetworkTracker extends BaseWifiTracker {
// Cache containing saved StandardWifiEntries. Must be accessed only by the worker thread.
private final List<StandardWifiEntry> mStandardWifiEntryCache = new ArrayList<>();
// Cache containing saved PasspointWifiEntries. Must be accessed only by the worker thread.
- private final Map<String, PasspointWifiEntry> mPasspointWifiEntryCache = new HashMap<>();
-
- private NetworkInfo mCurrentNetworkInfo;
- private WifiEntry mConnectedWifiEntry;
+ private final Map<String, PasspointWifiEntry> mPasspointWifiEntryCache = new ArrayMap<>();
public SavedNetworkTracker(@NonNull Lifecycle lifecycle, @NonNull Context context,
@NonNull WifiManager wifiManager,
@@ -149,25 +146,125 @@ public class SavedNetworkTracker extends BaseWifiTracker {
}
}
+ /** Check whether or not CA certificate is set.
+ *
+ * WifiEnterpriseConfig::hasCaCertificate() is only available
+ * after API level 33.
+ */
+ private static boolean hasCaCertificate(WifiEnterpriseConfig ec) {
+ if (ec.getCaCertificateAliases() != null) return true;
+ if (ec.getCaCertificates() != null) return true;
+ if (!TextUtils.isEmpty(ec.getCaPath())) return true;
+ return false;
+ }
+
+ private static boolean isCertificateUsedByConfiguration(
+ WifiConfiguration config, String certAlias) {
+ if (TextUtils.isEmpty(certAlias)) return false;
+ if (config == null) return false;
+ if (config.enterpriseConfig == null) return false;
+ WifiEnterpriseConfig ec = config.enterpriseConfig;
+ if (!ec.isEapMethodServerCertUsed()) return false;
+ if (!hasCaCertificate(ec) && TextUtils.isEmpty(ec.getClientCertificateAlias())) {
+ return false;
+ }
+
+ String[] aliases = ec.getCaCertificateAliases();
+ if (aliases != null) {
+ for (String s: aliases) {
+ if (!TextUtils.isEmpty(s) && certAlias.equals(s)) {
+ return true;
+ }
+ }
+ }
+ String clientAlias = ec.getClientCertificateAlias();
+ if (!TextUtils.isEmpty(clientAlias)
+ && certAlias.equals(clientAlias)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check whether or not a certifiate is required by saved networks or network suggestions.
+ */
+ @AnyThread
+ public boolean isCertificateRequired(String certAlias) {
+ // Configurations from Wi-Fi Network Suggestion
+ List<WifiConfiguration> configurations = mWifiManager.getNetworkSuggestions()
+ .stream().map(s -> s.getWifiConfiguration())
+ .collect(Collectors.toList());
+ // Configurations from regular Wi-Fi configurations.
+ configurations.addAll(mWifiManager.getConfiguredNetworks());
+
+ return configurations.stream()
+ .anyMatch(c -> isCertificateUsedByConfiguration(c, certAlias));
+ }
+
+ /**
+ * Returns a list of network names which requires the certificate alias.
+ *
+ * @return a list of network names.
+ */
+ @AnyThread
+ @NonNull
+ public List<String> getCertificateRequesterNames(String certAlias) {
+ // Configurations from Wi-Fi Network Suggestion
+ List<WifiConfiguration> configurations = mWifiManager.getNetworkSuggestions()
+ .stream().map(s -> s.getWifiConfiguration())
+ .collect(Collectors.toList());
+ // Configurations from regular Wi-Fi configurations.
+ configurations.addAll(mWifiManager.getConfiguredNetworks());
+
+ return configurations.stream()
+ .filter(c -> isCertificateUsedByConfiguration(c, certAlias))
+ .map(c -> c.SSID).collect(Collectors.toSet())
+ .stream().collect(Collectors.toList());
+ }
+
+ private List<WifiEntry> getAllWifiEntries() {
+ List<WifiEntry> allEntries = new ArrayList<>();
+ allEntries.addAll(mStandardWifiEntryCache);
+ allEntries.addAll(mPasspointWifiEntryCache.values());
+ return allEntries;
+ }
+
+ private void clearAllWifiEntries() {
+ mStandardWifiEntryCache.clear();
+ mPasspointWifiEntryCache.clear();
+ }
+
@WorkerThread
@Override
protected void handleOnStart() {
+ // Remove stale WifiEntries remaining from the last onStop().
+ clearAllWifiEntries();
+
+ // Update configs and scans
updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks());
updatePasspointWifiEntryConfigs(mWifiManager.getPasspointConfigurations());
+ mScanResultUpdater.update(mWifiManager.getScanResults());
conditionallyUpdateScanResults(true /* lastScanSucceeded */);
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- final Network currentNetwork = mWifiManager.getCurrentNetwork();
- mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
- updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
- updateWifiEntries();
- handleNetworkCapabilitiesChanged(
- mConnectivityManager.getNetworkCapabilities(currentNetwork));
- handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
- if (mConnectedWifiEntry != null) {
- mConnectedWifiEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
- mConnectedWifiEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+ // Trigger callbacks manually now to avoid waiting until the first calls to update state.
+ Network currentNetwork = mWifiManager.getCurrentNetwork();
+ if (currentNetwork != null) {
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(currentNetwork);
+ if (networkCapabilities != null) {
+ // getNetworkCapabilities(Network) obfuscates location info such as SSID and
+ // networkId, so we need to set the WifiInfo directly from WifiManager.
+ handleNetworkCapabilitiesChanged(currentNetwork,
+ new NetworkCapabilities.Builder(networkCapabilities)
+ .setTransportInfo(mWifiManager.getConnectionInfo())
+ .build());
+ }
+ LinkProperties linkProperties = mConnectivityManager.getLinkProperties(currentNetwork);
+ if (linkProperties != null) {
+ handleLinkPropertiesChanged(currentNetwork, linkProperties);
+ }
}
+ updateWifiEntries();
}
@WorkerThread
@@ -198,54 +295,65 @@ public class SavedNetworkTracker extends BaseWifiTracker {
@WorkerThread
@Override
protected void handleNetworkStateChangedAction(@NonNull Intent intent) {
- checkNotNull(intent, "Intent cannot be null!");
- mCurrentNetworkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
+ WifiInfo primaryWifiInfo = mWifiManager.getConnectionInfo();
+ NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ if (primaryWifiInfo == null || networkInfo == null) {
+ return;
+ }
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onPrimaryWifiInfoChanged(primaryWifiInfo, networkInfo);
+ }
}
@WorkerThread
@Override
- protected void handleRssiChangedAction() {
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- if (mConnectedWifiEntry != null) {
- mConnectedWifiEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
+ protected void handleLinkPropertiesChanged(
+ @NonNull Network network, @Nullable LinkProperties linkProperties) {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.updateLinkProperties(network, linkProperties);
}
}
@WorkerThread
@Override
- protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
- if (mConnectedWifiEntry != null
- && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- mConnectedWifiEntry.updateLinkProperties(linkProperties);
- }
+ protected void handleNetworkCapabilitiesChanged(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ updateConnectionInfo(network, capabilities);
+ updateWifiEntries();
}
@WorkerThread
@Override
- protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
- if (mConnectedWifiEntry != null
- && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- mConnectedWifiEntry.updateNetworkCapabilities(capabilities);
- mConnectedWifiEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+ protected void handleNetworkLost(@NonNull Network network) {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onNetworkLost(network);
}
+ updateWifiEntries();
}
@WorkerThread
@Override
protected void handleConnectivityReportAvailable(
@NonNull ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport) {
- if (mConnectedWifiEntry != null
- && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- mConnectedWifiEntry.updateConnectivityReport(connectivityReport);
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.updateConnectivityReport(connectivityReport);
}
}
+
@WorkerThread
- protected void handleDefaultRouteChanged() {
- if (mConnectedWifiEntry != null) {
- mConnectedWifiEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
- mConnectedWifiEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+ protected void handleDefaultNetworkCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onDefaultNetworkCapabilitiesChanged(network, networkCapabilities);
+ }
+ }
+
+ @WorkerThread
+ @Override
+ protected void handleDefaultNetworkLost() {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onDefaultNetworkLost();
}
}
@@ -255,20 +363,6 @@ public class SavedNetworkTracker extends BaseWifiTracker {
*/
private void updateWifiEntries() {
synchronized (mLock) {
- mConnectedWifiEntry = null;
- for (WifiEntry entry : mStandardWifiEntryCache) {
- if (entry.getConnectedState() != CONNECTED_STATE_DISCONNECTED) {
- mConnectedWifiEntry = entry;
- }
- }
- for (WifiEntry entry : mSubscriptionWifiEntries) {
- if (entry.getConnectedState() != CONNECTED_STATE_DISCONNECTED) {
- mConnectedWifiEntry = entry;
- }
- }
- if (mConnectedWifiEntry != null) {
- mConnectedWifiEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
- }
mSavedWifiEntries.clear();
mSavedWifiEntries.addAll(mStandardWifiEntryCache);
Collections.sort(mSavedWifiEntries, WifiEntry.TITLE_COMPARATOR);
@@ -413,24 +507,15 @@ public class SavedNetworkTracker extends BaseWifiTracker {
}
/**
- * Updates all WifiEntries with the current connection info.
- * @param wifiInfo WifiInfo of the current connection
- * @param networkInfo NetworkInfo of the current connection
+ * Updates all matching WifiEntries with the given connection info.
+ * @param network Network for which the NetworkCapabilities have changed.
+ * @param capabilities NetworkCapabilities that have changed.
*/
@WorkerThread
- private void updateConnectionInfo(@Nullable WifiInfo wifiInfo,
- @Nullable NetworkInfo networkInfo) {
- for (WifiEntry entry : mStandardWifiEntryCache) {
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- if (entry.getConnectedState() != CONNECTED_STATE_DISCONNECTED) {
- mConnectedWifiEntry = entry;
- }
- }
- for (WifiEntry entry : mPasspointWifiEntryCache.values()) {
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- if (entry.getConnectedState() != CONNECTED_STATE_DISCONNECTED) {
- mConnectedWifiEntry = entry;
- }
+ private void updateConnectionInfo(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onNetworkCapabilitiesChanged(network, capabilities);
}
}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/ScanResultUpdater.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/ScanResultUpdater.java
index 533849a7b..5e3df2ccd 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/ScanResultUpdater.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/ScanResultUpdater.java
@@ -17,13 +17,13 @@
package com.android.wifitrackerlib;
import android.net.wifi.ScanResult;
+import android.util.ArrayMap;
import android.util.Pair;
import androidx.annotation.NonNull;
import java.time.Clock;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -33,7 +33,7 @@ import java.util.Map;
* Thread-safe.
*/
public class ScanResultUpdater {
- private Map<Pair<String, String>, ScanResult> mScanResultsBySsidAndBssid = new HashMap<>();
+ private Map<Pair<String, String>, ScanResult> mScanResultsBySsidAndBssid = new ArrayMap<>();
private final long mMaxScanAgeMillis;
private final Object mLock = new Object();
private final Clock mClock;
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
index 1a05aace8..b1a8f83e7 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
@@ -26,12 +26,13 @@ import static java.util.stream.Collectors.toList;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkInfo;
+import android.net.NetworkCapabilities;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
+import android.telephony.SubscriptionManager;
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
@@ -50,8 +51,6 @@ public class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
private final StandardWifiEntryKey mKey;
private final StandardWifiEntry mChosenEntry;
- private final boolean mIsNetworkRequest;
- private NetworkInfo mCurrentNetworkInfo;
public StandardNetworkDetailsTracker(@NonNull Lifecycle lifecycle,
@NonNull Context context,
@@ -84,11 +83,9 @@ public class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
mainHandler, workerHandler, clock, maxScanAgeMillis, scanIntervalMillis, TAG);
mKey = new StandardWifiEntryKey(key);
if (mKey.isNetworkRequest()) {
- mIsNetworkRequest = true;
mChosenEntry = new NetworkRequestEntry(mInjector, mContext, mMainHandler, mKey,
mWifiManager, false /* forSavedNetworksPage */);
} else {
- mIsNetworkRequest = false;
mChosenEntry = new StandardWifiEntry(mInjector, mContext, mMainHandler, mKey,
mWifiManager, false /* forSavedNetworksPage */);
}
@@ -136,15 +133,24 @@ public class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
private void updateStartInfo() {
conditionallyUpdateScanResults(true /* lastScanSucceeded */);
conditionallyUpdateConfig();
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- final Network currentNetwork = mWifiManager.getCurrentNetwork();
- mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
- mChosenEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
- handleNetworkCapabilitiesChanged(
- mConnectivityManager.getNetworkCapabilities(currentNetwork));
- handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
- mChosenEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
- mChosenEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+ handleDefaultSubscriptionChanged(SubscriptionManager.getDefaultDataSubscriptionId());
+ Network currentNetwork = mWifiManager.getCurrentNetwork();
+ if (currentNetwork != null) {
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(currentNetwork);
+ if (networkCapabilities != null) {
+ // getNetworkCapabilities(Network) obfuscates location info such as SSID and
+ // networkId, so we need to set the WifiInfo directly from WifiManager.
+ handleNetworkCapabilitiesChanged(currentNetwork,
+ new NetworkCapabilities.Builder(networkCapabilities)
+ .setTransportInfo(mWifiManager.getConnectionInfo())
+ .build());
+ }
+ LinkProperties linkProperties = mConnectivityManager.getLinkProperties(currentNetwork);
+ if (linkProperties != null) {
+ handleLinkPropertiesChanged(currentNetwork, linkProperties);
+ }
+ }
}
/**
@@ -159,13 +165,15 @@ public class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
long scanAgeWindow = mMaxScanAgeMillis;
if (lastScanSucceeded) {
- cacheNewScanResults();
+ mScanResultUpdater.update(mWifiManager.getScanResults());
} else {
// Scan failed, increase scan age window to prevent WifiEntry list from
// clearing prematurely.
scanAgeWindow += mScanIntervalMillis;
}
- mChosenEntry.updateScanResultInfo(mScanResultUpdater.getScanResults(scanAgeWindow));
+ mChosenEntry.updateScanResultInfo(mScanResultUpdater.getScanResults(scanAgeWindow).stream()
+ .filter(scan -> new ScanResultKey(scan).equals(mKey.getScanResultKey()))
+ .collect(toList()));
}
/**
@@ -179,15 +187,6 @@ public class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
.collect(toList()));
}
- /**
- * Updates ScanResultUpdater with new ScanResults matching mChosenEntry.
- */
- private void cacheNewScanResults() {
- mScanResultUpdater.update(mWifiManager.getScanResults().stream()
- .filter(scan -> new ScanResultKey(scan).equals(mKey.getScanResultKey()))
- .collect(toList()));
- }
-
private boolean configMatches(@NonNull WifiConfiguration config) {
if (config.isPasspoint()) {
return false;
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
index d32f80240..95ab2599c 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
@@ -50,13 +50,15 @@ import android.app.admin.DevicePolicyManager;
import android.app.admin.WifiSsidPolicy;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
+import android.net.wifi.MloLink;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
import android.os.Handler;
import android.os.SystemClock;
@@ -66,12 +68,12 @@ import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import androidx.core.os.BuildCompat;
@@ -83,7 +85,6 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -96,7 +97,6 @@ import java.util.stream.Collectors;
*
* This type of WifiEntry can represent both open and saved networks.
*/
-@VisibleForTesting
public class StandardWifiEntry extends WifiEntry {
static final String TAG = "StandardWifiEntry";
public static final String KEY_PREFIX = "StandardWifiEntry:";
@@ -104,13 +104,13 @@ public class StandardWifiEntry extends WifiEntry {
@NonNull private final StandardWifiEntryKey mKey;
@NonNull private final WifiTrackerInjector mInjector;
- @NonNull private final Context mContext;
+ @NonNull protected final Context mContext;
// Map of security type to matching scan results
- @NonNull private final Map<Integer, List<ScanResult>> mMatchingScanResults = new HashMap<>();
+ @NonNull private final Map<Integer, List<ScanResult>> mMatchingScanResults = new ArrayMap<>();
// Map of security type to matching WifiConfiguration
// TODO: Change this to single WifiConfiguration once we can get multiple security type configs.
- @NonNull private final Map<Integer, WifiConfiguration> mMatchingWifiConfigs = new HashMap<>();
+ @NonNull private final Map<Integer, WifiConfiguration> mMatchingWifiConfigs = new ArrayMap<>();
// List of the target scan results to be displayed. This should match the highest available
// security from all of the matched WifiConfigurations.
@@ -187,10 +187,6 @@ public class StandardWifiEntry extends WifiEntry {
@Override
public synchronized String getSummary(boolean concise) {
- if (hasAdminRestrictions()) {
- return mContext.getString(R.string.wifitrackerlib_admin_restricted_network);
- }
-
StringJoiner sj = new StringJoiner(mContext.getString(
R.string.wifitrackerlib_summary_separator));
@@ -211,7 +207,7 @@ public class StandardWifiEntry extends WifiEntry {
mTargetWifiConfig,
mNetworkCapabilities,
mIsDefaultNetwork,
- mIsLowQuality,
+ isLowQuality(),
mConnectivityReport);
break;
default:
@@ -419,7 +415,8 @@ public class StandardWifiEntry extends WifiEntry {
@Override
public synchronized boolean canSignIn() {
- return mNetworkCapabilities != null
+ return mNetwork != null
+ && mNetworkCapabilities != null
&& mNetworkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
}
@@ -427,11 +424,8 @@ public class StandardWifiEntry extends WifiEntry {
@Override
public void signIn(@Nullable SignInCallback callback) {
if (canSignIn()) {
- // canSignIn() implies that this WifiEntry is the currently connected network, so use
- // getCurrentNetwork() to start the captive portal app.
NonSdkApiWrapper.startCaptivePortalApp(
- mContext.getSystemService(ConnectivityManager.class),
- mWifiManager.getCurrentNetwork());
+ mContext.getSystemService(ConnectivityManager.class), mNetwork);
}
}
@@ -528,6 +522,9 @@ public class StandardWifiEntry extends WifiEntry {
return;
}
+ // Refresh the current config so we don't overwrite any changes that we haven't gotten
+ // the CONFIGURED_NETWORKS_CHANGED broadcast for yet.
+ refreshTargetWifiConfig();
if (meteredChoice == METERED_CHOICE_AUTO) {
mTargetWifiConfig.meteredOverride = WifiConfiguration.METERED_OVERRIDE_NONE;
} else if (meteredChoice == METERED_CHOICE_METERED) {
@@ -560,7 +557,9 @@ public class StandardWifiEntry extends WifiEntry {
if (!canSetPrivacy()) {
return;
}
-
+ // Refresh the current config so we don't overwrite any changes that we haven't gotten
+ // the CONFIGURED_NETWORKS_CHANGED broadcast for yet.
+ refreshTargetWifiConfig();
mTargetWifiConfig.macRandomizationSetting = privacy == PRIVACY_RANDOMIZED_MAC
? WifiConfiguration.RANDOMIZATION_AUTO : WifiConfiguration.RANDOMIZATION_NONE;
mWifiManager.save(mTargetWifiConfig, null /* listener */);
@@ -673,6 +672,17 @@ public class StandardWifiEntry extends WifiEntry {
}
@Override
+ public synchronized String getBandString() {
+ if (mWifiInfo != null) {
+ return Utils.getBandString(mContext, mWifiInfo);
+ }
+ if (!mTargetScanResults.isEmpty()) {
+ return Utils.getBandString(mContext, mTargetScanResults.get(0).frequency);
+ }
+ return "";
+ }
+
+ @Override
public synchronized boolean shouldEditBeforeConnect() {
WifiConfiguration wifiConfig = getWifiConfiguration();
if (wifiConfig == null) {
@@ -681,7 +691,8 @@ public class StandardWifiEntry extends WifiEntry {
// The network is disabled because of one of the authentication problems.
NetworkSelectionStatus networkSelectionStatus = wifiConfig.getNetworkSelectionStatus();
- if (networkSelectionStatus.getNetworkSelectionStatus() != NETWORK_SELECTION_ENABLED) {
+ if (networkSelectionStatus.getNetworkSelectionStatus() != NETWORK_SELECTION_ENABLED
+ || !networkSelectionStatus.hasEverConnected()) {
if (networkSelectionStatus.getDisableReasonCounter(DISABLED_AUTHENTICATION_FAILURE) > 0
|| networkSelectionStatus.getDisableReasonCounter(
DISABLED_BY_WRONG_PASSWORD) > 0
@@ -740,8 +751,9 @@ public class StandardWifiEntry extends WifiEntry {
@WorkerThread
@Override
- synchronized void updateNetworkCapabilities(@Nullable NetworkCapabilities capabilities) {
- super.updateNetworkCapabilities(capabilities);
+ synchronized void onNetworkCapabilitiesChanged(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ super.onNetworkCapabilitiesChanged(network, capabilities);
// Auto-open an available captive portal if the user manually connected to this network.
if (canSignIn() && mShouldAutoOpenCaptivePortal) {
@@ -800,6 +812,15 @@ public class StandardWifiEntry extends WifiEntry {
}
}
+ private void refreshTargetWifiConfig() {
+ for (WifiConfiguration config : mWifiManager.getPrivilegedConfiguredNetworks()) {
+ if (config.networkId == mTargetWifiConfig.networkId) {
+ mTargetWifiConfig = config;
+ break;
+ }
+ }
+ }
+
@Override
protected synchronized void updateSecurityTypes() {
mTargetSecurityTypes.clear();
@@ -872,8 +893,7 @@ public class StandardWifiEntry extends WifiEntry {
}
@WorkerThread
- protected synchronized boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo,
- @NonNull NetworkInfo networkInfo) {
+ protected synchronized boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo) {
if (wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) {
return false;
}
@@ -942,7 +962,7 @@ public class StandardWifiEntry extends WifiEntry {
}
// TODO(b/227622961): Remove the suppression once the linter recognizes BuildCompat.isAtLeastT()
- @SuppressLint("NewApi")
+ @SuppressLint({"NewApi", "SwitchIntDef"})
private synchronized String getScanResultDescription(ScanResult scanResult, long nowMs) {
final StringBuilder description = new StringBuilder();
description.append(" \n{");
@@ -957,7 +977,35 @@ public class StandardWifiEntry extends WifiEntry {
if (BuildCompat.isAtLeastT() && wifiStandard == ScanResult.WIFI_STANDARD_11BE) {
description.append(",mldMac=").append(scanResult.getApMldMacAddress());
description.append(",linkId=").append(scanResult.getApMloLinkId());
- description.append(",affLinks=").append(scanResult.getAffiliatedMloLinks());
+ description.append(",affLinks=");
+ StringJoiner affLinks = new StringJoiner(",", "[", "]");
+ for (MloLink link : scanResult.getAffiliatedMloLinks()) {
+ final int scanResultBand;
+ switch (link.getBand()) {
+ case WifiScanner.WIFI_BAND_24_GHZ:
+ scanResultBand = ScanResult.WIFI_BAND_24_GHZ;
+ break;
+ case WifiScanner.WIFI_BAND_5_GHZ:
+ scanResultBand = ScanResult.WIFI_BAND_5_GHZ;
+ break;
+ case WifiScanner.WIFI_BAND_6_GHZ:
+ scanResultBand = ScanResult.WIFI_BAND_6_GHZ;
+ break;
+ case WifiScanner.WIFI_BAND_60_GHZ:
+ scanResultBand = ScanResult.WIFI_BAND_60_GHZ;
+ break;
+ default:
+ Log.e(TAG, "Unknown MLO link band: " + link.getBand());
+ scanResultBand = ScanResult.UNSPECIFIED;
+ break;
+ }
+ affLinks.add(new StringJoiner(",", "{", "}")
+ .add("apMacAddr=" + link.getApMacAddress())
+ .add("freq=" + ScanResult.convertChannelToFrequencyMhzIfSupported(
+ link.getChannel(), scanResultBand))
+ .toString());
+ }
+ description.append(affLinks.toString());
}
final int ageSeconds = (int) (nowMs - scanResult.timestamp / 1000) / 1000;
description.append(",").append(ageSeconds).append("s");
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
index 22c3765d6..3392ac2e6 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
@@ -16,6 +16,7 @@
package com.android.wifitrackerlib;
+import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED;
@@ -30,10 +31,13 @@ import android.net.ConnectivityDiagnosticsManager;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
+import android.net.TransportInfo;
+import android.net.wifi.MloLink;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiScanner;
import android.os.Build;
import android.os.PersistableBundle;
import android.os.UserHandle;
@@ -48,6 +52,7 @@ import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+import androidx.core.os.BuildCompat;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -196,9 +201,13 @@ public class Utils {
*/
static int getSingleSecurityTypeFromMultipleSecurityTypes(
@NonNull List<Integer> securityTypes) {
+ if (securityTypes.size() == 0) {
+ return WifiInfo.SECURITY_TYPE_UNKNOWN;
+ }
if (securityTypes.size() == 1) {
return securityTypes.get(0);
- } else if (securityTypes.size() == 2) {
+ }
+ if (securityTypes.size() == 2) {
if (securityTypes.contains(WifiInfo.SECURITY_TYPE_OPEN)) {
return WifiInfo.SECURITY_TYPE_OPEN;
}
@@ -209,7 +218,8 @@ public class Utils {
return WifiInfo.SECURITY_TYPE_EAP;
}
}
- return WifiInfo.SECURITY_TYPE_UNKNOWN;
+ // Default to the first security type if we don't need any special mapping.
+ return securityTypes.get(0);
}
/**
@@ -243,11 +253,13 @@ public class Utils {
final String suggestionOrSpecifierLabel =
getSuggestionOrSpecifierLabel(context, wifiConfiguration);
if (!TextUtils.isEmpty(suggestionOrSpecifierLabel)) {
- if (!isDefaultNetwork) {
- sj.add(context.getString(R.string.wifitrackerlib_available_via_app,
+ if (isDefaultNetwork || (networkCapabilities != null
+ && NonSdkApiWrapper.isOemCapabilities(networkCapabilities))) {
+ sj.add(context.getString(R.string.wifitrackerlib_connected_via_app,
suggestionOrSpecifierLabel));
} else {
- sj.add(context.getString(R.string.wifitrackerlib_connected_via_app,
+ // Pretend that non-default, non-OEM networks are unconnected.
+ sj.add(context.getString(R.string.wifitrackerlib_available_via_app,
suggestionOrSpecifierLabel));
}
shouldShowConnected = false;
@@ -397,31 +409,38 @@ public class Utils {
}
// Check for any failure messages to display
+ NetworkSelectionStatus networkSelectionStatus =
+ wifiConfiguration.getNetworkSelectionStatus();
if (wifiConfiguration.hasNoInternetAccess()) {
- int messageID =
- wifiConfiguration.getNetworkSelectionStatus().getNetworkSelectionStatus()
- == NETWORK_SELECTION_PERMANENTLY_DISABLED
- ? R.string.wifitrackerlib_wifi_no_internet_no_reconnect
- : R.string.wifitrackerlib_wifi_no_internet;
- return context.getString(messageID);
- } else if (wifiConfiguration.getNetworkSelectionStatus().getNetworkSelectionStatus()
- != NETWORK_SELECTION_ENABLED) {
- WifiConfiguration.NetworkSelectionStatus networkStatus =
- wifiConfiguration.getNetworkSelectionStatus();
- switch (networkStatus.getNetworkSelectionDisableReason()) {
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
- case WifiConfiguration.NetworkSelectionStatus
- .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION:
+ if (networkSelectionStatus.getNetworkSelectionStatus()
+ == NETWORK_SELECTION_PERMANENTLY_DISABLED) {
+ return context.getString(R.string.wifitrackerlib_wifi_no_internet_no_reconnect);
+ }
+ return context.getString(R.string.wifitrackerlib_wifi_no_internet);
+ }
+ if (networkSelectionStatus.getNetworkSelectionStatus() != NETWORK_SELECTION_ENABLED) {
+ switch (networkSelectionStatus.getNetworkSelectionDisableReason()) {
+ case NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES:
+ if (!networkSelectionStatus.hasEverConnected()
+ && networkSelectionStatus.getDisableReasonCounter(
+ NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE) > 0) {
+ return context.getString(
+ R.string.wifitrackerlib_wifi_disabled_password_failure);
+ }
+ break;
+ case NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
+ case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS:
+ case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION:
return context.getString(
R.string.wifitrackerlib_wifi_disabled_password_failure);
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
+ case NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
return context.getString(R.string.wifitrackerlib_wifi_check_password_try_again);
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
+ case NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
return context.getString(R.string.wifitrackerlib_wifi_disabled_network_failure);
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
+ case NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
return context.getString(R.string.wifitrackerlib_wifi_disabled_generic);
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT:
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY:
+ case NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT:
+ case NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY:
return context.getString(R.string.wifitrackerlib_wifi_no_internet_no_reconnect);
case DISABLED_TRANSITION_DISABLE_INDICATION:
return context.getString(
@@ -429,6 +448,13 @@ public class Utils {
default:
break;
}
+ } else { // NETWORK_SELECTION_ENABLED
+ // Show failure message if we've gotten AUTHENTICATION_FAILURE and have never connected
+ // before, which usually indicates the credentials are wrong.
+ if (networkSelectionStatus.getDisableReasonCounter(DISABLED_AUTHENTICATION_FAILURE) > 0
+ && !networkSelectionStatus.hasEverConnected()) {
+ return context.getString(R.string.wifitrackerlib_wifi_disabled_password_failure);
+ }
}
switch (wifiConfiguration.getRecentFailureReason()) {
case WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA:
@@ -883,7 +909,7 @@ public class Utils {
try {
netPart = InetAddress.getByAddress(array);
} catch (UnknownHostException e) {
- throw new RuntimeException("getNetworkPart error - " + e.toString());
+ throw new IllegalArgumentException("getNetworkPart error - " + e.toString());
}
return netPart;
}
@@ -893,7 +919,7 @@ public class Utils {
*/
public static void maskRawAddress(byte[] array, int prefixLength) {
if (prefixLength < 0 || prefixLength > array.length * 8) {
- throw new RuntimeException("IP address with " + array.length
+ throw new IllegalArgumentException("IP address with " + array.length
+ " bytes has invalid prefix length " + prefixLength);
}
@@ -901,7 +927,9 @@ public class Utils {
int remainder = prefixLength % 8;
byte mask = (byte) (0xFF << (8 - remainder));
- if (offset < array.length) array[offset] = (byte) (array[offset] & mask);
+ if (offset < array.length) {
+ array[offset] = (byte) (array[offset] & mask);
+ }
offset++;
@@ -1030,8 +1058,7 @@ public class Utils {
}
/**
- * Converts a ScanResult.WIFI_STANDARD_ value to a display string if available, or an
- * empty string if there is no corresponding display string.
+ * Converts a ScanResult.WIFI_STANDARD_ value to a display string.
*/
public static String getStandardString(@NonNull Context context, int standard) {
switch (standard) {
@@ -1051,4 +1078,70 @@ public class Utils {
return context.getString(R.string.wifitrackerlib_wifi_standard_unknown);
}
}
+
+ /**
+ * Converts a frequency in MHz to the display string of the corresponding Wi-Fi band.
+ */
+ public static String getBandString(@NonNull Context context, int freqMhz) {
+ if (freqMhz >= WifiEntry.MIN_FREQ_24GHZ && freqMhz < WifiEntry.MAX_FREQ_24GHZ) {
+ return context.getResources().getString(R.string.wifitrackerlib_wifi_band_24_ghz);
+ } else if (freqMhz >= WifiEntry.MIN_FREQ_5GHZ && freqMhz < WifiEntry.MAX_FREQ_5GHZ) {
+ return context.getResources().getString(R.string.wifitrackerlib_wifi_band_5_ghz);
+ } else if (freqMhz >= WifiEntry.MIN_FREQ_6GHZ && freqMhz < WifiEntry.MAX_FREQ_6GHZ) {
+ return context.getResources().getString(R.string.wifitrackerlib_wifi_band_6_ghz);
+ } else {
+ return context.getResources().getString(R.string.wifitrackerlib_wifi_band_unknown);
+ }
+ }
+
+ /**
+ * Converts the band info in WifiInfo to the display string of the corresponding Wi-Fi band(s).
+ */
+ public static String getBandString(@NonNull Context context, @NonNull WifiInfo wifiInfo) {
+ if (!BuildCompat.isAtLeastU()) {
+ return getBandString(context, wifiInfo.getFrequency());
+ }
+
+ StringJoiner sj = new StringJoiner(
+ context.getResources().getString(R.string.wifitrackerlib_multiband_separator));
+ wifiInfo.getAssociatedMloLinks().stream()
+ .filter((link) -> link.getState() == MloLink.MLO_LINK_STATE_ACTIVE)
+ .map(MloLink::getBand)
+ .distinct()
+ .sorted()
+ .forEach((band) -> {
+ switch (band) {
+ case WifiScanner.WIFI_BAND_24_GHZ:
+ sj.add(context.getResources()
+ .getString(R.string.wifitrackerlib_wifi_band_24_ghz));
+ break;
+ case WifiScanner.WIFI_BAND_5_GHZ:
+ sj.add(context.getResources()
+ .getString(R.string.wifitrackerlib_wifi_band_5_ghz));
+ break;
+ case WifiScanner.WIFI_BAND_6_GHZ:
+ sj.add(context.getResources()
+ .getString(R.string.wifitrackerlib_wifi_band_6_ghz));
+ break;
+ default:
+ sj.add(context.getResources()
+ .getString(R.string.wifitrackerlib_wifi_band_unknown));
+ }
+ });
+ if (sj.length() == 0) {
+ return getBandString(context, wifiInfo.getFrequency());
+ }
+ return sj.toString();
+ }
+
+ /**
+ * Gets the WifiInfo from a NetworkCapabilities if there is one.
+ */
+ public static WifiInfo getWifiInfo(@NonNull NetworkCapabilities capabilities) {
+ TransportInfo transportInfo = capabilities.getTransportInfo();
+ if (transportInfo instanceof WifiInfo) {
+ return (WifiInfo) transportInfo;
+ }
+ return NonSdkApiWrapper.getVcnWifiInfo(capabilities);
+ }
}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
index d7120988c..0c575f73b 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
@@ -26,6 +26,7 @@ import static com.android.wifitrackerlib.Utils.getSingleSecurityTypeFromMultiple
import android.net.ConnectivityDiagnosticsManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.RouteInfo;
@@ -40,8 +41,8 @@ import androidx.annotation.IntDef;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
+import androidx.core.os.BuildCompat;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -50,6 +51,7 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -205,8 +207,11 @@ public class WifiEntry {
* Default comparator for sorting WifiEntries on a Wi-Fi picker list.
*/
public static Comparator<WifiEntry> WIFI_PICKER_COMPARATOR =
- Comparator.comparing((WifiEntry entry) -> entry.getConnectedState()
- != CONNECTED_STATE_CONNECTED)
+ Comparator.comparing((WifiEntry entry) -> !entry.isPrimaryNetwork())
+ .thenComparing((WifiEntry entry) ->
+ entry.getConnectedState() != CONNECTED_STATE_CONNECTED)
+ .thenComparing((WifiEntry entry) -> !(entry instanceof KnownNetworkEntry))
+ .thenComparing((WifiEntry entry) -> !(entry instanceof HotspotNetworkEntry))
.thenComparing((WifiEntry entry) -> !entry.canConnect())
.thenComparing((WifiEntry entry) -> !entry.isSubscription())
.thenComparing((WifiEntry entry) -> !entry.isSaved())
@@ -220,8 +225,7 @@ public class WifiEntry {
public static Comparator<WifiEntry> TITLE_COMPARATOR =
Comparator.comparing((WifiEntry entry) -> entry.getTitle());
- @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
- final boolean mForSavedNetworksPage;
+ protected final boolean mForSavedNetworksPage;
protected final WifiManager mWifiManager;
@@ -232,7 +236,9 @@ public class WifiEntry {
protected int mLevel = WIFI_LEVEL_UNREACHABLE;
protected WifiInfo mWifiInfo;
protected NetworkInfo mNetworkInfo;
+ protected Network mNetwork;
protected NetworkCapabilities mNetworkCapabilities;
+ protected NetworkCapabilities mDefaultNetworkCapabilities;
protected ConnectivityDiagnosticsManager.ConnectivityReport mConnectivityReport;
protected ConnectedInfo mConnectedInfo;
@@ -244,7 +250,6 @@ public class WifiEntry {
protected boolean mCalledDisconnect = false;
protected boolean mIsDefaultNetwork;
- protected boolean mIsLowQuality;
private Optional<ManageSubscriptionAction> mManageSubscriptionAction = Optional.empty();
@@ -268,25 +273,29 @@ public class WifiEntry {
/** Returns connection state of the network defined by the CONNECTED_STATE constants */
@ConnectedState
public synchronized int getConnectedState() {
- if (mNetworkInfo == null) {
- return CONNECTED_STATE_DISCONNECTED;
+ // If we have NetworkCapabilities, then we're L3 connected.
+ if (mNetworkCapabilities != null) {
+ return CONNECTED_STATE_CONNECTED;
}
- switch (mNetworkInfo.getDetailedState()) {
- case SCANNING:
- case CONNECTING:
- case AUTHENTICATING:
- case OBTAINING_IPADDR:
- case VERIFYING_POOR_LINK:
- case CAPTIVE_PORTAL_CHECK:
- return CONNECTED_STATE_CONNECTING;
- case CONNECTED:
- return CONNECTED_STATE_CONNECTED;
- default:
- return CONNECTED_STATE_DISCONNECTED;
+ // Use NetworkInfo to provide the connecting state before we're L3 connected.
+ if (mNetworkInfo != null) {
+ switch (mNetworkInfo.getDetailedState()) {
+ case SCANNING:
+ case CONNECTING:
+ case AUTHENTICATING:
+ case OBTAINING_IPADDR:
+ case VERIFYING_POOR_LINK:
+ case CAPTIVE_PORTAL_CHECK:
+ case CONNECTED:
+ return CONNECTED_STATE_CONNECTING;
+ default:
+ return CONNECTED_STATE_DISCONNECTED;
+ }
}
- }
+ return CONNECTED_STATE_DISCONNECTED;
+ }
/** Returns the display title. This is most commonly the SSID of a network. */
@NonNull
@@ -325,12 +334,14 @@ public class WifiEntry {
/**
* Returns whether the level icon for this network should show an X or not.
+ * By default, this means any connected network that has no/low-quality internet access.
*/
public boolean shouldShowXLevelIcon() {
return getConnectedState() != CONNECTED_STATE_DISCONNECTED
&& mConnectivityReport != null
- && (!hasInternetAccess() || !mIsDefaultNetwork)
- && !canSignIn();
+ && (!hasInternetAccess() || isLowQuality())
+ && !canSignIn()
+ && isPrimaryNetwork();
}
/**
@@ -351,6 +362,36 @@ public class WifiEntry {
}
/**
+ * Returns whether this network is the primary Wi-Fi network or not.
+ */
+ public boolean isPrimaryNetwork() {
+ if (getConnectedState() == CONNECTED_STATE_DISCONNECTED) {
+ // In case we have mNetworkInfo but the state is disconnected.
+ return false;
+ }
+ return mNetworkInfo != null
+ || (mWifiInfo != null && NonSdkApiWrapper.isPrimary(mWifiInfo));
+ }
+
+ /**
+ * Returns whether this network is considered low quality.
+ */
+ public boolean isLowQuality() {
+ if (!isPrimaryNetwork()) {
+ return false;
+ }
+ if (mNetworkCapabilities == null) {
+ return false;
+ }
+ if (mDefaultNetworkCapabilities == null) {
+ return false;
+ }
+ return mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ && mDefaultNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && !mDefaultNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
+ }
+
+ /**
* Returns the SSID of the entry, if applicable. Null otherwise.
*/
@Nullable
@@ -360,9 +401,10 @@ public class WifiEntry {
/**
* Returns the security type defined by the SECURITY constants
- * DEPRECATED: Use getSecurityTypes() which can return multiple security types.
+ * @deprecated Use getSecurityTypes() which can return multiple security types.
*/
// TODO(b/187554920): Remove this and move all clients to getSecurityTypes()
+ @Deprecated
@Security
public int getSecurity() {
switch (getSingleSecurityTypeFromMultipleSecurityTypes(getSecurityTypes())) {
@@ -611,6 +653,11 @@ public class WifiEntry {
return "";
}
+ /** Returns the string displayed for the Wi-Fi band */
+ public String getBandString() {
+ return "";
+ }
+
/** Returns whether subscription of the entry is expired */
public boolean isExpired() {
return false;
@@ -671,7 +718,7 @@ public class WifiEntry {
.append(", isDefaultNetwork:")
.append(mIsDefaultNetwork)
.append(", isLowQuality:")
- .append(mIsLowQuality);
+ .append(isLowQuality());
}
return sb.toString();
}
@@ -814,85 +861,153 @@ public class WifiEntry {
}
/**
- * Returns whether or not the supplied WifiInfo and NetworkInfo represent this WifiEntry
+ * Returns whether the supplied WifiInfo represents this WifiEntry
*/
- protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo,
- @NonNull NetworkInfo networkInfo) {
+ protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo) {
return false;
}
/**
- * Updates information regarding the current network connection. If the supplied WifiInfo and
- * NetworkInfo do not match this WifiEntry, then the WifiEntry will update to be
- * unconnected.
+ * Updates this WifiEntry with the given primary WifiInfo/NetworkInfo if they match.
+ * @param primaryWifiInfo Primary WifiInfo that has changed
+ * @param networkInfo NetworkInfo of the primary network
*/
- @WorkerThread
- synchronized void updateConnectionInfo(
- @Nullable WifiInfo wifiInfo, @Nullable NetworkInfo networkInfo) {
- if (wifiInfo != null && networkInfo != null
- && connectionInfoMatches(wifiInfo, networkInfo)) {
- // Connection info matches, so the WifiInfo/NetworkInfo represent this network and
- // the network is currently connecting or connected.
- mWifiInfo = wifiInfo;
- mNetworkInfo = networkInfo;
- final int wifiInfoRssi = wifiInfo.getRssi();
- if (wifiInfoRssi != INVALID_RSSI) {
- mLevel = mWifiManager.calculateSignalLevel(wifiInfoRssi);
+ synchronized void onPrimaryWifiInfoChanged(
+ @NonNull WifiInfo primaryWifiInfo, @NonNull NetworkInfo networkInfo) {
+ if (!connectionInfoMatches(primaryWifiInfo)) {
+ if (mNetworkInfo != null) {
+ mNetworkInfo = null;
+ notifyOnUpdated();
}
- if (getConnectedState() == CONNECTED_STATE_CONNECTED) {
- if (mCalledConnect) {
- mCalledConnect = false;
- mCallbackHandler.post(() -> {
- final ConnectCallback connectCallback = mConnectCallback;
- if (connectCallback != null) {
- connectCallback.onConnectResult(
- ConnectCallback.CONNECT_STATUS_SUCCESS);
- }
- });
- }
+ return;
+ }
+ mNetworkInfo = networkInfo;
+ notifyOnUpdated();
+ }
- if (mConnectedInfo == null) {
- mConnectedInfo = new ConnectedInfo();
- }
- mConnectedInfo.frequencyMhz = wifiInfo.getFrequency();
- mConnectedInfo.linkSpeedMbps = wifiInfo.getLinkSpeed();
- mConnectedInfo.wifiStandard = wifiInfo.getWifiStandard();
+ /**
+ * Updates this WifiEntry with the given NetworkCapabilities if it matches.
+ */
+ @WorkerThread
+ synchronized void onNetworkCapabilitiesChanged(
+ @NonNull Network network,
+ @NonNull NetworkCapabilities capabilities) {
+ WifiInfo wifiInfo = Utils.getWifiInfo(capabilities);
+ if (wifiInfo == null) {
+ return;
+ }
+
+ if (!connectionInfoMatches(wifiInfo)) {
+ if (network.equals(mNetwork)) {
+ // WifiInfo doesn't match but the Network matches. This may be due to linked
+ // roaming, so treat as a disconnect.
+ onNetworkLost(network);
}
- } else { // Connection info doesn't matched, so this network is disconnected
- mWifiInfo = null;
- mNetworkInfo = null;
- mNetworkCapabilities = null;
- mConnectedInfo = null;
- mConnectivityReport = null;
- mIsDefaultNetwork = false;
- mIsLowQuality = false;
- if (mCalledDisconnect) {
- mCalledDisconnect = false;
+ return;
+ }
+
+ // Treat non-primary, non-OEM connections as disconnected.
+ if (!NonSdkApiWrapper.isPrimary(wifiInfo)
+ && !NonSdkApiWrapper.isOemCapabilities(capabilities)) {
+ onNetworkLost(network);
+ return;
+ }
+
+ // Connection info matches, so the Network/NetworkCapabilities represent this network
+ // and the network is currently connecting or connected.
+ mWifiInfo = wifiInfo;
+ mNetwork = network;
+ mNetworkCapabilities = capabilities;
+ final int wifiInfoRssi = mWifiInfo.getRssi();
+ if (wifiInfoRssi != INVALID_RSSI) {
+ mLevel = mWifiManager.calculateSignalLevel(wifiInfoRssi);
+ }
+ if (getConnectedState() == CONNECTED_STATE_CONNECTED) {
+ if (mCalledConnect) {
+ mCalledConnect = false;
mCallbackHandler.post(() -> {
- final DisconnectCallback disconnectCallback = mDisconnectCallback;
- if (disconnectCallback != null) {
- disconnectCallback.onDisconnectResult(
- DisconnectCallback.DISCONNECT_STATUS_SUCCESS);
+ final ConnectCallback connectCallback = mConnectCallback;
+ if (connectCallback != null) {
+ connectCallback.onConnectResult(
+ ConnectCallback.CONNECT_STATUS_SUCCESS);
}
});
}
+
+ if (mConnectedInfo == null) {
+ mConnectedInfo = new ConnectedInfo();
+ }
+ mConnectedInfo.frequencyMhz = mWifiInfo.getFrequency();
+ mConnectedInfo.linkSpeedMbps = mWifiInfo.getLinkSpeed();
+ mConnectedInfo.wifiStandard = mWifiInfo.getWifiStandard();
}
updateSecurityTypes();
notifyOnUpdated();
}
+ /**
+ * Updates this WifiEntry as disconnected if the network matches.
+ * @param network Network that was lost
+ */
+ synchronized void onNetworkLost(@NonNull Network network) {
+ if (!network.equals(mNetwork)) {
+ return;
+ }
+
+ // Network matches, so this network is disconnected.
+ mWifiInfo = null;
+ mNetworkInfo = null;
+ mNetworkCapabilities = null;
+ mConnectedInfo = null;
+ mConnectivityReport = null;
+ mIsDefaultNetwork = false;
+ if (mCalledDisconnect) {
+ mCalledDisconnect = false;
+ mCallbackHandler.post(() -> {
+ final DisconnectCallback disconnectCallback = mDisconnectCallback;
+ if (disconnectCallback != null) {
+ disconnectCallback.onDisconnectResult(
+ DisconnectCallback.DISCONNECT_STATUS_SUCCESS);
+ }
+ });
+ }
+ updateSecurityTypes();
+ notifyOnUpdated();
+ }
+
+ /**
+ * Updates this WifiEntry as the default network if it matches.
+ */
+ @WorkerThread
+ synchronized void onDefaultNetworkCapabilitiesChanged(
+ @NonNull Network network,
+ @NonNull NetworkCapabilities capabilities) {
+ onNetworkCapabilitiesChanged(network, capabilities);
+ mDefaultNetworkCapabilities = capabilities;
+ mIsDefaultNetwork = network.equals(mNetwork);
+ notifyOnUpdated();
+ }
+
+ /**
+ * Notifies this WifiEntry that the default network was lost.
+ */
+ synchronized void onDefaultNetworkLost() {
+ mDefaultNetworkCapabilities = null;
+ mIsDefaultNetwork = false;
+ notifyOnUpdated();
+ }
+
// Called to indicate the security types should be updated to match new information about the
// network.
protected void updateSecurityTypes() {
// Do nothing;
}
- // Method for WifiTracker to update the link properties, which is valid for all WifiEntry types.
+ // Updates this WifiEntry's link properties if the network matches.
@WorkerThread
- synchronized void updateLinkProperties(@Nullable LinkProperties linkProperties) {
- if (linkProperties == null || getConnectedState() != CONNECTED_STATE_CONNECTED) {
- mConnectedInfo = null;
- notifyOnUpdated();
+ synchronized void updateLinkProperties(
+ @NonNull Network network, @NonNull LinkProperties linkProperties) {
+ if (!network.equals(mNetwork)) {
return;
}
@@ -909,7 +1024,7 @@ public class WifiEntry {
new byte[]{(byte) 255, (byte) 255, (byte) 255, (byte) 255});
mConnectedInfo.subnetMask = getNetworkPart(
all, addr.getPrefixLength()).getHostAddress();
- } catch (UnknownHostException e) {
+ } catch (UnknownHostException | IllegalArgumentException e) {
// Leave subnet null;
}
} else if (addr.getAddress() instanceof Inet6Address) {
@@ -934,34 +1049,14 @@ public class WifiEntry {
notifyOnUpdated();
}
- @WorkerThread
- synchronized void setIsDefaultNetwork(boolean isDefaultNetwork) {
- mIsDefaultNetwork = isDefaultNetwork;
- notifyOnUpdated();
- }
-
- @WorkerThread
- synchronized void setIsLowQuality(boolean isLowQuality) {
- mIsLowQuality = isLowQuality;
- }
-
- // Method for WifiTracker to update a connected WifiEntry's network capabilities.
- @WorkerThread
- synchronized void updateNetworkCapabilities(@Nullable NetworkCapabilities capabilities) {
- mNetworkCapabilities = capabilities;
- if (mConnectedInfo == null) {
- return;
- }
- mConnectedInfo.networkCapabilities = mNetworkCapabilities;
- notifyOnUpdated();
- }
-
// Method for WifiTracker to update a connected WifiEntry's validation status.
@WorkerThread
synchronized void updateConnectivityReport(
- @Nullable ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport) {
- mConnectivityReport = connectivityReport;
- notifyOnUpdated();
+ @NonNull ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport) {
+ if (connectivityReport.getNetwork().equals(mNetwork)) {
+ mConnectivityReport = connectivityReport;
+ notifyOnUpdated();
+ }
}
synchronized String getWifiInfoDescription() {
@@ -979,6 +1074,12 @@ public class WifiEntry {
sj.add(String.format("%.1f,", mWifiInfo.getRetriedTxPacketsPerSecond()));
sj.add(String.format("%.1f ", mWifiInfo.getLostTxPacketsPerSecond()));
sj.add(String.format("rx=%.1f", mWifiInfo.getSuccessfulRxPacketsPerSecond()));
+ if (BuildCompat.isAtLeastT() && mWifiInfo.getApMldMacAddress() != null) {
+ sj.add("mldMac = " + mWifiInfo.getApMldMacAddress());
+ sj.add("linkId = " + mWifiInfo.getApMloLinkId());
+ sj.add("affLinks = " + Arrays.toString(
+ mWifiInfo.getAffiliatedMloLinks().toArray()));
+ }
}
return sj.toString();
}
@@ -1071,8 +1172,10 @@ public class WifiEntry {
.append(getConnectedInfo())
.append(",hasInternet:")
.append(hasInternetAccess())
- .append(",isDefaultNetwork:")
+ .append(",isDefault:")
.append(mIsDefaultNetwork)
+ .append(",isPrimary:")
+ .append(isPrimaryNetwork())
.toString();
}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
index 397ad90d6..dc2a7b4dc 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
@@ -16,20 +16,21 @@
package com.android.wifitrackerlib;
+import static android.os.Build.VERSION_CODES;
+
import static androidx.core.util.Preconditions.checkNotNull;
import static com.android.wifitrackerlib.OsuWifiEntry.osuProviderToOsuWifiEntryKey;
import static com.android.wifitrackerlib.PasspointWifiEntry.uniqueIdToPasspointWifiEntryKey;
import static com.android.wifitrackerlib.StandardWifiEntry.ScanResultKey;
import static com.android.wifitrackerlib.StandardWifiEntry.StandardWifiEntryKey;
-import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
-import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTING;
import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_DISCONNECTED;
import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityDiagnosticsManager;
@@ -44,6 +45,10 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
import android.os.Handler;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
@@ -60,6 +65,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
+import androidx.core.os.BuildCompat;
import androidx.lifecycle.Lifecycle;
import java.time.Clock;
@@ -90,14 +96,15 @@ public class WifiPickerTracker extends BaseWifiTracker {
// Lock object for data returned by the public API
private final Object mLock = new Object();
- // List representing return value of the getWifiEntries() API
- @GuardedBy("mLock") private final List<WifiEntry> mWifiEntries = new ArrayList<>();
- // Reference to the WifiEntry representing the network that is currently connected to
- private WifiEntry mConnectedWifiEntry;
+ // List representing the return value of the getActiveWifiEntries() API
+ @GuardedBy("mLock")
+ @NonNull private final List<WifiEntry> mActiveWifiEntries = new ArrayList<>();
+ // List representing the return value of the getWifiEntries() API
+ @GuardedBy("mLock")
+ @NonNull private final List<WifiEntry> mWifiEntries = new ArrayList<>();
// NetworkRequestEntry representing a network that was connected through the NetworkRequest API
private NetworkRequestEntry mNetworkRequestEntry;
- private NetworkInfo mCurrentNetworkInfo;
// Cache containing saved WifiConfigurations mapped by StandardWifiEntry key
private final Map<StandardWifiEntryKey, List<WifiConfiguration>> mStandardWifiConfigCache =
new ArrayMap<>();
@@ -126,6 +133,11 @@ public class WifiPickerTracker extends BaseWifiTracker {
private int mNumSavedNetworks;
+ private final List<KnownNetwork> mKnownNetworkDataCache = new ArrayList<>();
+ private final List<KnownNetworkEntry> mKnownNetworkEntryCache = new ArrayList<>();
+ private final List<HotspotNetwork> mHotspotNetworkDataCache = new ArrayList<>();
+ private final List<HotspotNetworkEntry> mHotspotNetworkEntryCache = new ArrayList<>();
+
/**
* Constructor for WifiPickerTracker.
* @param lifecycle Lifecycle this is tied to for lifecycle callbacks.
@@ -172,15 +184,36 @@ public class WifiPickerTracker extends BaseWifiTracker {
}
/**
- * Returns the WifiEntry representing the current connection.
+ * Returns the WifiEntry representing the current primary connection.
*/
@AnyThread
public @Nullable WifiEntry getConnectedWifiEntry() {
- return mConnectedWifiEntry;
+ synchronized (mLock) {
+ if (mActiveWifiEntries.isEmpty()) {
+ return null;
+ }
+ // Primary entry is sorted to be first.
+ WifiEntry primaryWifiEntry = mActiveWifiEntries.get(0);
+ if (!primaryWifiEntry.isPrimaryNetwork()) {
+ return null;
+ }
+ return primaryWifiEntry;
+ }
}
/**
- * Returns a list of in-range WifiEntries.
+ * Returns a list of all connected/connecting Wi-Fi entries, including the primary and any
+ * secondary connections.
+ */
+ @AnyThread
+ public @NonNull List<WifiEntry> getActiveWifiEntries() {
+ synchronized (mLock) {
+ return new ArrayList<>(mActiveWifiEntries);
+ }
+ }
+
+ /**
+ * Returns a list of disconnected, in-range WifiEntries.
*
* The currently connected entry is omitted and may be accessed through
* {@link #getConnectedWifiEntry()}
@@ -226,36 +259,80 @@ public class WifiPickerTracker extends BaseWifiTracker {
return mPasspointConfigCache.size();
}
+ private List<WifiEntry> getAllWifiEntries() {
+ List<WifiEntry> allEntries = new ArrayList<>();
+ allEntries.addAll(mStandardWifiEntryCache);
+ allEntries.addAll(mSuggestedWifiEntryCache);
+ allEntries.addAll(mPasspointWifiEntryCache.values());
+ allEntries.addAll(mOsuWifiEntryCache.values());
+ if (mEnableSharedConnectivityFeature) {
+ allEntries.addAll(mKnownNetworkEntryCache);
+ allEntries.addAll(mHotspotNetworkEntryCache);
+ }
+ if (mNetworkRequestEntry != null) {
+ allEntries.add(mNetworkRequestEntry);
+ }
+ if (mMergedCarrierEntry != null) {
+ allEntries.add(mMergedCarrierEntry);
+ }
+ return allEntries;
+ }
+
+ private void clearAllWifiEntries() {
+ mStandardWifiEntryCache.clear();
+ mSuggestedWifiEntryCache.clear();
+ mPasspointWifiEntryCache.clear();
+ mOsuWifiEntryCache.clear();
+ if (mEnableSharedConnectivityFeature) {
+ mKnownNetworkEntryCache.clear();
+ mHotspotNetworkEntryCache.clear();
+ }
+ mNetworkRequestEntry = null;
+ mMergedCarrierEntry = null;
+ }
+
@WorkerThread
@Override
protected void handleOnStart() {
+ // Remove stale WifiEntries remaining from the last onStop().
+ clearAllWifiEntries();
+
+ // Update configs and scans
updateWifiConfigurations(mWifiManager.getPrivilegedConfiguredNetworks());
updatePasspointConfigurations(mWifiManager.getPasspointConfigurations());
mScanResultUpdater.update(mWifiManager.getScanResults());
conditionallyUpdateScanResults(true /* lastScanSucceeded */);
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- final Network currentNetwork = mWifiManager.getCurrentNetwork();
- mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
- updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
+
+ // Trigger callbacks manually now to avoid waiting until the first calls to update state.
+ handleDefaultSubscriptionChanged(SubscriptionManager.getDefaultDataSubscriptionId());
+ Network currentNetwork = mWifiManager.getCurrentNetwork();
+ if (currentNetwork != null) {
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(currentNetwork);
+ if (networkCapabilities != null) {
+ // getNetworkCapabilities(Network) obfuscates location info such as SSID and
+ // networkId, so we need to set the WifiInfo directly from WifiManager.
+ handleNetworkCapabilitiesChanged(currentNetwork,
+ new NetworkCapabilities.Builder(networkCapabilities)
+ .setTransportInfo(mWifiManager.getConnectionInfo())
+ .build());
+ }
+ LinkProperties linkProperties = mConnectivityManager.getLinkProperties(currentNetwork);
+ if (linkProperties != null) {
+ handleLinkPropertiesChanged(currentNetwork, linkProperties);
+ }
+ }
notifyOnNumSavedNetworksChanged();
notifyOnNumSavedSubscriptionsChanged();
- handleDefaultSubscriptionChanged(SubscriptionManager.getDefaultDataSubscriptionId());
updateWifiEntries();
-
- // Populate mConnectedWifiEntry with information from missed callbacks.
- handleNetworkCapabilitiesChanged(
- mConnectivityManager.getNetworkCapabilities(currentNetwork));
- handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
- handleDefaultRouteChanged();
}
@WorkerThread
@Override
protected void handleWifiStateChangedAction() {
- if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLED) {
- updateConnectionInfo(null, null);
+ if (getWifiState() == WifiManager.WIFI_STATE_DISABLED) {
+ clearAllWifiEntries();
}
- conditionallyUpdateScanResults(true /* lastScanSucceeded */);
updateWifiEntries();
}
@@ -287,6 +364,12 @@ public class WifiPickerTracker extends BaseWifiTracker {
updateNetworkRequestEntryScans(scanResults);
updatePasspointWifiEntryScans(scanResults);
updateOsuWifiEntryScans(scanResults);
+ if (mEnableSharedConnectivityFeature && BuildCompat.isAtLeastU()) {
+ updateKnownNetworkEntryScans(scanResults);
+ // Updating the hotspot entries here makes the UI more reliable when switching pages or
+ // when toggling settings while the internet picker is shown.
+ updateHotspotNetworkEntries();
+ }
notifyOnNumSavedNetworksChanged();
notifyOnNumSavedSubscriptionsChanged();
updateWifiEntries();
@@ -295,73 +378,69 @@ public class WifiPickerTracker extends BaseWifiTracker {
@WorkerThread
@Override
protected void handleNetworkStateChangedAction(@NonNull Intent intent) {
- checkNotNull(intent, "Intent cannot be null!");
- mCurrentNetworkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
+ WifiInfo primaryWifiInfo = mWifiManager.getConnectionInfo();
+ NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ if (primaryWifiInfo == null || networkInfo == null) {
+ return;
+ }
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onPrimaryWifiInfoChanged(primaryWifiInfo, networkInfo);
+ }
updateWifiEntries();
}
@WorkerThread
@Override
- protected void handleRssiChangedAction() {
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- if (mConnectedWifiEntry != null) {
- mConnectedWifiEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
- }
- if (mMergedCarrierEntry != null) {
- mMergedCarrierEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
+ protected void handleLinkPropertiesChanged(
+ @NonNull Network network, @Nullable LinkProperties linkProperties) {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.updateLinkProperties(network, linkProperties);
}
}
@WorkerThread
@Override
- protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
- if (mConnectedWifiEntry != null
- && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- mConnectedWifiEntry.updateLinkProperties(linkProperties);
- }
- if (mMergedCarrierEntry != null) {
- mMergedCarrierEntry.updateLinkProperties(linkProperties);
- }
+ protected void handleNetworkCapabilitiesChanged(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ updateNetworkCapabilities(network, capabilities);
+ updateWifiEntries();
}
@WorkerThread
@Override
- protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
- if (mConnectedWifiEntry != null
- && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- mConnectedWifiEntry.updateNetworkCapabilities(capabilities);
- mConnectedWifiEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+ protected void handleNetworkLost(@NonNull Network network) {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onNetworkLost(network);
}
- if (mMergedCarrierEntry != null) {
- mMergedCarrierEntry.updateNetworkCapabilities(capabilities);
+ if (mNetworkRequestEntry != null
+ && mNetworkRequestEntry.getConnectedState() == CONNECTED_STATE_DISCONNECTED) {
+ mNetworkRequestEntry = null;
}
+ updateWifiEntries();
}
@WorkerThread
@Override
protected void handleConnectivityReportAvailable(
@NonNull ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport) {
- if (mConnectedWifiEntry != null
- && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- mConnectedWifiEntry.updateConnectivityReport(connectivityReport);
- }
- if (mMergedCarrierEntry != null) {
- mMergedCarrierEntry.updateConnectivityReport(connectivityReport);
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.updateConnectivityReport(connectivityReport);
}
}
@WorkerThread
- protected void handleDefaultRouteChanged() {
- if (mConnectedWifiEntry != null) {
- mConnectedWifiEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
- mConnectedWifiEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+ protected void handleDefaultNetworkCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onDefaultNetworkCapabilitiesChanged(network, networkCapabilities);
}
- if (mMergedCarrierEntry != null) {
- if (mMergedCarrierEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
- mMergedCarrierEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
- }
- mMergedCarrierEntry.updateIsCellDefaultRoute(mIsCellDefaultRoute);
+ }
+
+ @WorkerThread
+ @Override
+ protected void handleDefaultNetworkLost() {
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onDefaultNetworkLost();
}
}
@@ -371,52 +450,125 @@ public class WifiPickerTracker extends BaseWifiTracker {
updateMergedCarrierEntry(defaultSubId);
}
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ @Override
+ protected void handleKnownNetworksUpdated(List<KnownNetwork> networks) {
+ if (mEnableSharedConnectivityFeature) {
+ mKnownNetworkDataCache.clear();
+ mKnownNetworkDataCache.addAll(networks);
+ updateKnownNetworkEntryScans(mScanResultUpdater.getScanResults());
+ updateWifiEntries();
+ }
+ }
+
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ @Override
+ protected void handleHotspotNetworksUpdated(List<HotspotNetwork> networks) {
+ if (mEnableSharedConnectivityFeature) {
+ mHotspotNetworkDataCache.clear();
+ mHotspotNetworkDataCache.addAll(networks);
+ updateHotspotNetworkEntries();
+ updateWifiEntries();
+ }
+ }
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ protected void handleHotspotNetworkConnectionStatusChanged(
+ @NonNull HotspotNetworkConnectionStatus status) {
+ mHotspotNetworkEntryCache.stream().filter(
+ entry -> entry.getHotspotNetworkEntryKey().getDeviceId()
+ == status.getHotspotNetwork().getDeviceId()).forEach(
+ entry -> entry.onConnectionStatusChanged(status.getStatus()));
+ }
+
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ @Override
+ protected void handleKnownNetworkConnectionStatusChanged(
+ @NonNull KnownNetworkConnectionStatus status) {
+ final ScanResultKey key = new ScanResultKey(status.getKnownNetwork().getSsid(),
+ status.getKnownNetwork().getSecurityTypes().stream().toList());
+ mKnownNetworkEntryCache.stream().filter(
+ entry -> entry.getStandardWifiEntryKey().getScanResultKey().equals(key)).forEach(
+ entry -> entry.onConnectionStatusChanged(status.getStatus()));
+ }
+
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ @Override
+ protected void handleServiceConnected() {
+ if (mEnableSharedConnectivityFeature) {
+ mKnownNetworkDataCache.clear();
+ mKnownNetworkDataCache.addAll(mSharedConnectivityManager.getKnownNetworks());
+ mHotspotNetworkDataCache.clear();
+ mHotspotNetworkDataCache.addAll(mSharedConnectivityManager.getHotspotNetworks());
+ updateKnownNetworkEntryScans(mScanResultUpdater.getScanResults());
+ updateHotspotNetworkEntries();
+ updateWifiEntries();
+ }
+ }
+
/**
* Update the list returned by getWifiEntries() with the current states of the entry caches.
*/
@WorkerThread
protected void updateWifiEntries() {
synchronized (mLock) {
- mConnectedWifiEntry = mStandardWifiEntryCache.stream().filter(entry -> {
- final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState();
- return connectedState == CONNECTED_STATE_CONNECTED
- || connectedState == CONNECTED_STATE_CONNECTING;
- }).findAny().orElse(null /* other */);
- if (mConnectedWifiEntry == null) {
- mConnectedWifiEntry = mSuggestedWifiEntryCache.stream().filter(entry -> {
- final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState();
- return connectedState == CONNECTED_STATE_CONNECTED
- || connectedState == CONNECTED_STATE_CONNECTING;
- }).findAny().orElse(null /* other */);
+ mActiveWifiEntries.clear();
+ mActiveWifiEntries.addAll(mStandardWifiEntryCache);
+ mActiveWifiEntries.addAll(mSuggestedWifiEntryCache);
+ mActiveWifiEntries.addAll(mPasspointWifiEntryCache.values());
+ if (mEnableSharedConnectivityFeature) {
+ mActiveWifiEntries.addAll(mHotspotNetworkEntryCache);
}
- if (mConnectedWifiEntry == null) {
- mConnectedWifiEntry = mPasspointWifiEntryCache.values().stream().filter(entry -> {
- final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState();
- return connectedState == CONNECTED_STATE_CONNECTED
- || connectedState == CONNECTED_STATE_CONNECTING;
- }).findAny().orElse(null /* other */);
+ if (mNetworkRequestEntry != null) {
+ mActiveWifiEntries.add(mNetworkRequestEntry);
}
- if (mConnectedWifiEntry == null && mNetworkRequestEntry != null
- && mNetworkRequestEntry.getConnectedState() != CONNECTED_STATE_DISCONNECTED) {
- mConnectedWifiEntry = mNetworkRequestEntry;
- }
- if (mConnectedWifiEntry != null) {
- mConnectedWifiEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
+ mActiveWifiEntries.removeIf(entry ->
+ entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED);
+ Set<ScanResultKey> activeHotspotNetworkKeys = new ArraySet<>();
+ for (WifiEntry entry : mActiveWifiEntries) {
+ if (entry instanceof HotspotNetworkEntry) {
+ activeHotspotNetworkKeys.add(((HotspotNetworkEntry) entry)
+ .getHotspotNetworkEntryKey().getScanResultKey());
+ }
}
+ mActiveWifiEntries.removeIf(entry -> entry instanceof StandardWifiEntry
+ && activeHotspotNetworkKeys.contains(
+ ((StandardWifiEntry) entry).getStandardWifiEntryKey().getScanResultKey()));
+ mActiveWifiEntries.sort(WifiEntry.WIFI_PICKER_COMPARATOR);
mWifiEntries.clear();
final Set<ScanResultKey> scanResultKeysWithVisibleSuggestions =
mSuggestedWifiEntryCache.stream()
- .filter(entry -> entry.isUserShareable()
- || entry == mConnectedWifiEntry)
+ .filter(entry -> {
+ if (entry.isUserShareable()) return true;
+ synchronized (mLock) {
+ return mActiveWifiEntries.contains(entry);
+ }
+ })
.map(entry -> entry.getStandardWifiEntryKey().getScanResultKey())
.collect(Collectors.toSet());
Set<String> passpointUtf8Ssids = new ArraySet<>();
for (PasspointWifiEntry passpointWifiEntry : mPasspointWifiEntryCache.values()) {
passpointUtf8Ssids.addAll(passpointWifiEntry.getAllUtf8Ssids());
}
+ Set<ScanResultKey> knownNetworkKeys = new ArraySet<>();
+ for (KnownNetworkEntry knownNetworkEntry : mKnownNetworkEntryCache) {
+ knownNetworkKeys.add(
+ knownNetworkEntry.getStandardWifiEntryKey().getScanResultKey());
+ }
+ Set<ScanResultKey> hotspotNetworkKeys = new ArraySet<>();
+ for (HotspotNetworkEntry hotspotNetworkEntry : mHotspotNetworkEntryCache) {
+ if (!hotspotNetworkEntry.getHotspotNetworkEntryKey().isVirtualEntry()) {
+ hotspotNetworkKeys.add(
+ hotspotNetworkEntry.getHotspotNetworkEntryKey().getScanResultKey());
+ }
+ }
for (StandardWifiEntry entry : mStandardWifiEntryCache) {
entry.updateAdminRestrictions();
- if (entry == mConnectedWifiEntry) {
+ if (mActiveWifiEntries.contains(entry)) {
continue;
}
if (!entry.isSaved()) {
@@ -429,6 +581,18 @@ public class WifiPickerTracker extends BaseWifiTracker {
continue;
}
}
+ if (mEnableSharedConnectivityFeature) {
+ // Filter out any StandardWifiEntry that is matched with a KnownNetworkEntry
+ if (knownNetworkKeys
+ .contains(entry.getStandardWifiEntryKey().getScanResultKey())) {
+ continue;
+ }
+ // Filter out any StandardWifiEntry that is matched with a HotspotNetworkEntry
+ if (hotspotNetworkKeys
+ .contains(entry.getStandardWifiEntryKey().getScanResultKey())) {
+ continue;
+ }
+ }
mWifiEntries.add(entry);
}
mWifiEntries.addAll(mSuggestedWifiEntryCache.stream().filter(entry ->
@@ -441,9 +605,18 @@ public class WifiPickerTracker extends BaseWifiTracker {
&& !entry.isAlreadyProvisioned()).collect(toList()));
mWifiEntries.addAll(getContextualWifiEntries().stream().filter(entry ->
entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList()));
+ if (mEnableSharedConnectivityFeature) {
+ mWifiEntries.addAll(mKnownNetworkEntryCache.stream().filter(entry ->
+ entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(
+ toList()));
+ mWifiEntries.addAll(mHotspotNetworkEntryCache.stream().filter(entry ->
+ entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(
+ toList()));
+ }
Collections.sort(mWifiEntries, WifiEntry.WIFI_PICKER_COMPARATOR);
if (isVerboseLoggingEnabled()) {
- Log.v(TAG, "Connected WifiEntry: " + mConnectedWifiEntry);
+ Log.v(TAG, "Connected WifiEntries: "
+ + Arrays.toString(mActiveWifiEntries.toArray()));
Log.v(TAG, "Updated WifiEntries: " + Arrays.toString(mWifiEntries.toArray()));
}
}
@@ -467,8 +640,24 @@ public class WifiPickerTracker extends BaseWifiTracker {
}
mMergedCarrierEntry = new MergedCarrierEntry(mWorkerHandler, mWifiManager,
/* forSavedNetworksPage */ false, mContext, subId);
- mMergedCarrierEntry.updateConnectionInfo(
- mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
+ Network currentNetwork = mWifiManager.getCurrentNetwork();
+ if (currentNetwork != null) {
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(currentNetwork);
+ if (networkCapabilities != null) {
+ // getNetworkCapabilities(Network) obfuscates location info such as SSID and
+ // networkId, so we need to set the WifiInfo directly from WifiManager.
+ mMergedCarrierEntry.onNetworkCapabilitiesChanged(currentNetwork,
+ new NetworkCapabilities.Builder(networkCapabilities)
+ .setTransportInfo(mWifiManager.getConnectionInfo())
+ .build());
+ }
+ LinkProperties linkProperties =
+ mConnectivityManager.getLinkProperties(currentNetwork);
+ if (linkProperties != null) {
+ mMergedCarrierEntry.updateLinkProperties(currentNetwork, linkProperties);
+ }
+ }
}
notifyOnWifiEntriesChanged();
}
@@ -668,6 +857,132 @@ public class WifiPickerTracker extends BaseWifiTracker {
.removeIf(entry -> entry.getValue().getLevel() == WIFI_LEVEL_UNREACHABLE);
}
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ private void updateKnownNetworkEntryScans(@NonNull List<ScanResult> scanResults) {
+ checkNotNull(scanResults, "Scan Result list should not be null!");
+
+ // Group scans by ScanResultKey key
+ final Map<ScanResultKey, List<ScanResult>> scanResultsByKey = scanResults.stream()
+ .filter(scan -> !TextUtils.isEmpty(scan.SSID))
+ .collect(Collectors.groupingBy(ScanResultKey::new));
+
+ // Create a map of KnownNetwork data by ScanResultKey
+ final Map<ScanResultKey, KnownNetwork> knownNetworkDataByKey =
+ mKnownNetworkDataCache.stream().collect(Collectors.toMap(
+ data -> new ScanResultKey(data.getSsid(),
+ new ArrayList<>(data.getSecurityTypes())),
+ data -> data,
+ (data1, data2) -> {
+ Log.e(TAG,
+ "Encountered duplicate key data in "
+ + "updateKnownNetworkEntryScans");
+ return data1; // When duplicate data is encountered, use first one.
+ }));
+
+ // Create set of ScanResultKeys for known networks from service that are included in scan
+ final Set<ScanResultKey> newScanKeys = knownNetworkDataByKey.keySet().stream().filter(
+ scanResultsByKey::containsKey).collect(Collectors.toSet());
+
+ // Iterate through current entries and update each entry's scan results
+ mKnownNetworkEntryCache.forEach(entry -> {
+ final ScanResultKey scanKey = entry.getStandardWifiEntryKey().getScanResultKey();
+ newScanKeys.remove(scanKey);
+ // Update scan results if available, or set to null.
+ entry.updateScanResultInfo(scanResultsByKey.get(scanKey));
+ });
+
+ // Get network and capabilities if new network entries are being created
+ Network network = null;
+ NetworkCapabilities capabilities = null;
+ if (!newScanKeys.isEmpty()) {
+ network = mWifiManager.getCurrentNetwork();
+ if (network != null) {
+ capabilities = mConnectivityManager.getNetworkCapabilities(network);
+ if (capabilities != null) {
+ // getNetworkCapabilities(Network) obfuscates location info such as SSID and
+ // networkId, so we need to set the WifiInfo directly from WifiManager.
+ capabilities = new NetworkCapabilities.Builder(capabilities).setTransportInfo(
+ mWifiManager.getConnectionInfo()).build();
+ }
+ }
+ }
+
+ // Create new KnownNetworkEntry objects for each leftover group of scan results.
+ for (ScanResultKey scanKey : newScanKeys) {
+ final StandardWifiEntryKey entryKey =
+ new StandardWifiEntryKey(scanKey, true /* isTargetingNewNetworks */);
+ final KnownNetworkEntry newEntry = new KnownNetworkEntry(mInjector, mContext,
+ mMainHandler, entryKey, null /* configs */,
+ scanResultsByKey.get(scanKey), mWifiManager,
+ mSharedConnectivityManager, knownNetworkDataByKey.get(scanKey));
+ if (network != null && capabilities != null) {
+ newEntry.onNetworkCapabilitiesChanged(network, capabilities);
+ }
+ mKnownNetworkEntryCache.add(newEntry);
+ }
+
+ // Remove any entry that is now unreachable due to no scans or unsupported
+ // security types.
+ mKnownNetworkEntryCache.removeIf(
+ entry -> entry.getLevel() == WIFI_LEVEL_UNREACHABLE);
+ }
+
+ @TargetApi(VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @WorkerThread
+ private void updateHotspotNetworkEntries() {
+ // Map HotspotNetwork data by deviceID
+ final Map<Long, HotspotNetwork> hotspotNetworkDataById =
+ mHotspotNetworkDataCache.stream().collect(Collectors.toMap(
+ HotspotNetwork::getDeviceId,
+ data -> data,
+ (data1, data2) -> {
+ Log.e(TAG,
+ "Encountered duplicate key data in "
+ + "updateHotspotNetworkEntries");
+ return data1; // When duplicate data is encountered, use first one.
+ }));
+ final Set<Long> newDeviceIds = new ArraySet<>(hotspotNetworkDataById.keySet());
+
+ // Remove entries not in latest data set from service
+ mHotspotNetworkEntryCache.removeIf(
+ entry -> !newDeviceIds.contains(entry.getHotspotNetworkEntryKey().getDeviceId()));
+
+ // Iterate through entries and update HotspotNetwork data
+ mHotspotNetworkEntryCache.forEach(entry -> {
+ final Long deviceId = entry.getHotspotNetworkEntryKey().getDeviceId();
+ newDeviceIds.remove(deviceId);
+ entry.updateHotspotNetworkData(hotspotNetworkDataById.get(deviceId));
+ });
+
+ // Get network and capabilities if new network entries are being created
+ Network network = null;
+ NetworkCapabilities capabilities = null;
+ if (!newDeviceIds.isEmpty()) {
+ network = mWifiManager.getCurrentNetwork();
+ if (network != null) {
+ capabilities = mConnectivityManager.getNetworkCapabilities(network);
+ if (capabilities != null) {
+ // getNetworkCapabilities(Network) obfuscates location info such as SSID and
+ // networkId, so we need to set the WifiInfo directly from WifiManager.
+ capabilities = new NetworkCapabilities.Builder(capabilities).setTransportInfo(
+ mWifiManager.getConnectionInfo()).build();
+ }
+ }
+ }
+
+ // Create new HotspotNetworkEntry objects for each new device ID
+ for (Long deviceId : newDeviceIds) {
+ final HotspotNetworkEntry newEntry = new HotspotNetworkEntry(mInjector, mContext,
+ mMainHandler, mWifiManager, mSharedConnectivityManager,
+ hotspotNetworkDataById.get(deviceId));
+ if (network != null && capabilities != null) {
+ newEntry.onNetworkCapabilitiesChanged(network, capabilities);
+ }
+ mHotspotNetworkEntryCache.add(newEntry);
+ }
+ }
+
@WorkerThread
private void updateNetworkRequestEntryScans(@NonNull List<ScanResult> scanResults) {
checkNotNull(scanResults, "Scan Result list should not be null!");
@@ -694,6 +1009,10 @@ public class WifiPickerTracker extends BaseWifiTracker {
updateSuggestedWifiEntryScans(Collections.emptyList());
updatePasspointWifiEntryScans(Collections.emptyList());
updateOsuWifiEntryScans(Collections.emptyList());
+ if (mEnableSharedConnectivityFeature && BuildCompat.isAtLeastU()) {
+ mKnownNetworkEntryCache.clear();
+ mHotspotNetworkEntryCache.clear();
+ }
updateNetworkRequestEntryScans(Collections.emptyList());
updateContextualWifiEntryScans(Collections.emptyList());
return;
@@ -714,6 +1033,12 @@ public class WifiPickerTracker extends BaseWifiTracker {
updateSuggestedWifiEntryScans(scanResults);
updatePasspointWifiEntryScans(scanResults);
updateOsuWifiEntryScans(scanResults);
+ if (mEnableSharedConnectivityFeature && BuildCompat.isAtLeastU()) {
+ updateKnownNetworkEntryScans(scanResults);
+ // Updating the hotspot entries here makes the UI more reliable when switching pages or
+ // when toggling settings while the internet picker is shown.
+ updateHotspotNetworkEntries();
+ }
updateNetworkRequestEntryScans(scanResults);
updateContextualWifiEntryScans(scanResults);
}
@@ -730,7 +1055,6 @@ public class WifiPickerTracker extends BaseWifiTracker {
mStandardWifiConfigCache.clear();
mSuggestedConfigCache.clear();
mNetworkRequestConfigCache.clear();
- final List<WifiConfiguration> networkRequestConfigs = new ArrayList<>();
for (WifiConfiguration config : configs) {
if (config.carrierMerged) {
continue;
@@ -801,36 +1125,30 @@ public class WifiPickerTracker extends BaseWifiTracker {
}
/**
- * Updates all WifiEntries with the current connection info.
- * @param wifiInfo WifiInfo of the current connection
- * @param networkInfo NetworkInfo of the current connection
+ * Updates all matching WifiEntries with the given network capabilities. If there are
+ * currently no matching WifiEntries, then a new WifiEntry will be created for the capabilities.
+ * @param network Network for which the NetworkCapabilities have changed.
+ * @param capabilities NetworkCapabilities that have changed.
*/
@WorkerThread
- private void updateConnectionInfo(@Nullable WifiInfo wifiInfo,
- @Nullable NetworkInfo networkInfo) {
- for (WifiEntry entry : mStandardWifiEntryCache) {
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- }
- for (WifiEntry entry : mSuggestedWifiEntryCache) {
- entry.updateConnectionInfo(wifiInfo, networkInfo);
+ private void updateNetworkCapabilities(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ if (mStandardWifiConfigCache.size()
+ + mSuggestedConfigCache.size() + mPasspointWifiConfigCache.size()
+ + mNetworkRequestConfigCache.size() == 0) {
+ // We're connected but don't have any configured networks, so fetch the list of configs
+ // again. This can happen when we fetch the configured networks after SSR, but the Wifi
+ // thread times out waiting for driver restart and returns an empty list of networks.
+ updateWifiConfigurations(mWifiManager.getPrivilegedConfiguredNetworks());
}
- for (WifiEntry entry : mPasspointWifiEntryCache.values()) {
- entry.updateConnectionInfo(wifiInfo, networkInfo);
+ for (WifiEntry entry : getAllWifiEntries()) {
+ entry.onNetworkCapabilitiesChanged(network, capabilities);
}
- for (WifiEntry entry : mOsuWifiEntryCache.values()) {
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- }
- if (mNetworkRequestEntry != null) {
- mNetworkRequestEntry.updateConnectionInfo(wifiInfo, networkInfo);
- }
- updateNetworkRequestEntryConnectionInfo(wifiInfo, networkInfo);
- if (mMergedCarrierEntry != null) {
- mMergedCarrierEntry.updateConnectionInfo(wifiInfo, networkInfo);
- }
- // Create a StandardWifiEntry for the current connection if there are no scan results yet.
- conditionallyCreateConnectedStandardWifiEntry(wifiInfo, networkInfo);
- conditionallyCreateConnectedSuggestedWifiEntry(wifiInfo, networkInfo);
- conditionallyCreateConnectedPasspointWifiEntry(wifiInfo, networkInfo);
+ // Create a WifiEntry for the current connection if there are no scan results yet.
+ conditionallyCreateConnectedStandardWifiEntry(network, capabilities);
+ conditionallyCreateConnectedSuggestedWifiEntry(network, capabilities);
+ conditionallyCreateConnectedPasspointWifiEntry(network, capabilities);
+ conditionallyCreateConnectedNetworkRequestEntry(network, capabilities);
}
/**
@@ -838,10 +1156,11 @@ public class WifiPickerTracker extends BaseWifiTracker {
* created if there is no existing entry, or the existing entry doesn't match WifiInfo.
*/
@WorkerThread
- private void updateNetworkRequestEntryConnectionInfo(
- @Nullable WifiInfo wifiInfo, @Nullable NetworkInfo networkInfo) {
+ private void conditionallyCreateConnectedNetworkRequestEntry(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
final List<WifiConfiguration> matchingConfigs = new ArrayList<>();
+ WifiInfo wifiInfo = Utils.getWifiInfo(capabilities);
if (wifiInfo != null) {
for (int i = 0; i < mNetworkRequestConfigCache.size(); i++) {
final List<WifiConfiguration> configs = mNetworkRequestConfigCache.valueAt(i);
@@ -851,10 +1170,7 @@ public class WifiPickerTracker extends BaseWifiTracker {
}
}
}
-
- // WifiInfo isn't for any request configs, remove the NetworkRequestEntry
if (matchingConfigs.isEmpty()) {
- mNetworkRequestEntry = null;
return;
}
@@ -867,18 +1183,17 @@ public class WifiPickerTracker extends BaseWifiTracker {
mNetworkRequestEntry.updateConfig(matchingConfigs);
updateNetworkRequestEntryScans(mScanResultUpdater.getScanResults());
}
- mNetworkRequestEntry.updateConnectionInfo(wifiInfo, networkInfo);
+ mNetworkRequestEntry.onNetworkCapabilitiesChanged(network, capabilities);
}
/**
- * Creates and caches a StandardWifiEntry representing the current connection using the current
- * WifiInfo and NetworkInfo if there are no scans results available for the network yet.
- * @param wifiInfo WifiInfo of the current connection
- * @param networkInfo NetworkInfo of the current connection
+ * If the given network is a standard Wi-Fi network and there are no scan results for this
+ * network yet, create and cache a new StandardWifiEntry for it.
*/
@WorkerThread
- private void conditionallyCreateConnectedStandardWifiEntry(@Nullable WifiInfo wifiInfo,
- @Nullable NetworkInfo networkInfo) {
+ private void conditionallyCreateConnectedStandardWifiEntry(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ WifiInfo wifiInfo = Utils.getWifiInfo(capabilities);
if (wifiInfo == null || wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) {
return;
}
@@ -902,26 +1217,23 @@ public class WifiPickerTracker extends BaseWifiTracker {
final StandardWifiEntry connectedEntry =
new StandardWifiEntry(mInjector, mContext, mMainHandler, entryKey, configs,
null, mWifiManager, false /* forSavedNetworksPage */);
- connectedEntry.updateConnectionInfo(wifiInfo, networkInfo);
+ connectedEntry.onNetworkCapabilitiesChanged(network, capabilities);
mStandardWifiEntryCache.add(connectedEntry);
return;
}
}
/**
- * Creates and caches a suggested StandardWifiEntry representing the current connection using
- * the current WifiInfo and NetworkInfo if there are no scans results available for the network
- * yet.
- * @param wifiInfo WifiInfo of the current connection
- * @param networkInfo NetworkInfo of the current connection
+ * If the given network is a suggestion network and there are no scan results for this network
+ * yet, create and cache a new StandardWifiEntry for it.
*/
@WorkerThread
- private void conditionallyCreateConnectedSuggestedWifiEntry(@Nullable WifiInfo wifiInfo,
- @Nullable NetworkInfo networkInfo) {
+ private void conditionallyCreateConnectedSuggestedWifiEntry(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ WifiInfo wifiInfo = Utils.getWifiInfo(capabilities);
if (wifiInfo == null || wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) {
return;
}
-
final int connectedNetId = wifiInfo.getNetworkId();
for (List<WifiConfiguration> configs : mSuggestedConfigCache.values()) {
if (configs.isEmpty() || configs.get(0).networkId != connectedNetId) {
@@ -937,22 +1249,20 @@ public class WifiPickerTracker extends BaseWifiTracker {
final StandardWifiEntry connectedEntry =
new StandardWifiEntry(mInjector, mContext, mMainHandler, entryKey, configs,
null, mWifiManager, false /* forSavedNetworksPage */);
- connectedEntry.updateConnectionInfo(wifiInfo, networkInfo);
+ connectedEntry.onNetworkCapabilitiesChanged(network, capabilities);
mSuggestedWifiEntryCache.add(connectedEntry);
return;
}
}
-
/**
- * Creates and caches a PasspointWifiEntry representing the current connection using the current
- * WifiInfo and NetworkInfo if there are no scans results available for the network yet.
- * @param wifiInfo WifiInfo of the current connection
- * @param networkInfo NetworkInfo of the current connection
+ * If the given network is a Passpoint network and there are no scan results for this network
+ * yet, create and cache a new StandardWifiEntry for it.
*/
@WorkerThread
- private void conditionallyCreateConnectedPasspointWifiEntry(@Nullable WifiInfo wifiInfo,
- @Nullable NetworkInfo networkInfo) {
+ private void conditionallyCreateConnectedPasspointWifiEntry(
+ @NonNull Network network, @NonNull NetworkCapabilities capabilities) {
+ WifiInfo wifiInfo = Utils.getWifiInfo(capabilities);
if (wifiInfo == null || !wifiInfo.isPasspointAp()) {
return;
}
@@ -979,7 +1289,7 @@ public class WifiPickerTracker extends BaseWifiTracker {
cachedWifiConfig, mWifiManager,
false /* forSavedNetworksPage */);
}
- connectedEntry.updateConnectionInfo(wifiInfo, networkInfo);
+ connectedEntry.onNetworkCapabilitiesChanged(network, capabilities);
mPasspointWifiEntryCache.put(connectedEntry.getKey(), connectedEntry);
}
diff --git a/libs/WifiTrackerLib/tests/Android.bp b/libs/WifiTrackerLib/tests/Android.bp
index 1a6b57a05..3ce536c58 100644
--- a/libs/WifiTrackerLib/tests/Android.bp
+++ b/libs/WifiTrackerLib/tests/Android.bp
@@ -24,7 +24,7 @@ java_defaults {
"androidx.test.rules",
"frameworks-base-testutils",
"mockito-target-extended-minus-junit4",
- "truth-prebuilt",
+ "truth",
"Robolectric_all-target",
],
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/HotspotNetworkEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/HotspotNetworkEntryTest.java
new file mode 100644
index 000000000..9bbbd4c10
--- /dev/null
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/HotspotNetworkEntryTest.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wifitrackerlib;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
+
+import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
+import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_DISCONNECTED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
+import android.os.Handler;
+import android.os.test.TestLooper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class HotspotNetworkEntryTest {
+ @Mock private WifiEntry.WifiEntryCallback mMockListener;
+ @Mock private WifiEntry.ConnectCallback mMockConnectCallback;
+ @Mock private WifiEntry.DisconnectCallback mMockDisconnectCallback;
+ @Mock private WifiTrackerInjector mMockInjector;
+ @Mock private Context mMockContext;
+ @Mock private WifiManager mMockWifiManager;
+ @Mock private SharedConnectivityManager mMockSharedConnectivityManager;
+ @Mock private WifiInfo mMockWifiInfo;
+ @Mock private Network mMockNetwork;
+ @Mock private NetworkCapabilities mMockNetworkCapabilities;
+
+ private TestLooper mTestLooper;
+ private Handler mTestHandler;
+
+ private static final HotspotNetwork TEST_HOTSPOT_NETWORK_DATA = new HotspotNetwork.Builder()
+ .setDeviceId(1)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
+ .setNetworkName("Google Fi")
+ .setHotspotSsid("Instant Hotspot abcde")
+ .setHotspotBssid("0a:0b:0c:0d:0e:0f")
+ .addHotspotSecurityType(SECURITY_TYPE_PSK)
+ .build();
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mTestLooper = new TestLooper();
+ mTestHandler = new Handler(mTestLooper.getLooper());
+
+ when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
+ when(mMockWifiInfo.isPrimary()).thenReturn(true);
+ when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
+
+ when(mMockContext.getString(R.string.wifitrackerlib_hotspot_network_connecting))
+ .thenReturn("Connecting…");
+ when(mMockContext.getString(eq(R.string.wifitrackerlib_hotspot_network_summary),
+ anyString(), anyString()))
+ .thenAnswer(invocation -> {
+ Object[] args = invocation.getArguments();
+ return args[1] + " from " + args[2];
+ });
+ when(mMockContext.getString(eq(R.string.wifitrackerlib_hotspot_network_alternate),
+ anyString(), anyString()))
+ .thenAnswer(invocation -> {
+ Object[] args = invocation.getArguments();
+ return args[1] + " from " + args[2];
+ });
+ }
+
+ @Test
+ public void testConnectionInfoMatches_matchesBssid() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+ when(mMockWifiInfo.getBSSID()).thenReturn("00:00:00:00:00:00");
+
+ assertThat(entry.connectionInfoMatches(mMockWifiInfo)).isFalse();
+
+ when(mMockWifiInfo.getBSSID()).thenReturn("0a:0b:0c:0d:0e:0f");
+
+ assertThat(entry.connectionInfoMatches(mMockWifiInfo)).isTrue();
+ }
+
+ @Test
+ public void testOnNetworkCapabilitiesChanged_matchingBSSID_becomesConnected() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+ when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
+
+ // Ignore non-matching BSSID
+ when(mMockWifiInfo.getBSSID()).thenReturn("00:00:00:00:00:00");
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_DISCONNECTED);
+ assertThat(entry.canConnect()).isTrue();
+ assertThat(entry.canDisconnect()).isFalse();
+
+ // Matching BSSID should result in connected
+ when(mMockWifiInfo.getBSSID()).thenReturn("0a:0b:0c:0d:0e:0f");
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
+ assertThat(entry.canConnect()).isFalse();
+ assertThat(entry.canDisconnect()).isTrue();
+ }
+
+ @Test
+ public void testOnNetworkLost_matchingNetwork_becomesDisconnected() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+ when(mMockWifiInfo.getBSSID()).thenReturn("0a:0b:0c:0d:0e:0f");
+ when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+
+ // Non-matching network loss should be ignored
+ entry.onNetworkLost(mock(Network.class));
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
+ assertThat(entry.canConnect()).isFalse();
+ assertThat(entry.canDisconnect()).isTrue();
+
+ // Matching network loss should result in disconnected
+ entry.onNetworkLost(mMockNetwork);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_DISCONNECTED);
+ assertThat(entry.canConnect()).isTrue();
+ assertThat(entry.canDisconnect()).isFalse();
+ }
+
+ @Test
+ public void testGetTitle_usesDeviceName() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ assertThat(entry.getTitle()).isEqualTo("My Phone");
+ }
+
+ @Test
+ public void testGetSummary_usesHotspotNetworkData() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ assertThat(entry.getSummary()).isEqualTo("Google Fi from Pixel 7");
+ }
+
+ @Test
+ public void testGetAlternateSummary_usesHotspotNetworkData() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ assertThat(entry.getAlternateSummary()).isEqualTo("Google Fi from My Phone");
+ }
+
+ @Test
+ public void testGetSummary_connectionStatusEnabling_returnsConnectingString() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ entry.setListener(mMockListener);
+ entry.connect(mMockConnectCallback);
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT);
+ mTestLooper.dispatchAll();
+
+ verify(mMockConnectCallback, never()).onConnectResult(anyInt());
+
+ assertThat(entry.getSummary()).isEqualTo("Connecting…");
+ }
+
+ @Test
+ public void testGetSummary_connectionStatusFailure_resetsConnectingString() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+ entry.setListener(mMockListener);
+ entry.connect(mMockConnectCallback);
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT);
+ mTestLooper.dispatchAll();
+ assertThat(entry.getSummary()).isEqualTo("Connecting…");
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN_ERROR);
+ mTestLooper.dispatchAll();
+
+ assertThat(entry.getSummary()).isNotEqualTo("Connecting…");
+ }
+
+ @Test
+ public void testGetUpstreamConnectionStrength_usesHotspotNetworkData() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ assertThat(entry.getUpstreamConnectionStrength()).isEqualTo(3);
+ }
+
+ @Test
+ public void testGetNetworkType_usesHotspotNetworkData() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ assertThat(entry.getNetworkType()).isEqualTo(HotspotNetwork.NETWORK_TYPE_CELLULAR);
+ }
+
+ @Test
+ public void testGetDeviceType_usesHotspotNetworkData() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ assertThat(entry.getDeviceType()).isEqualTo(NetworkProviderInfo.DEVICE_TYPE_PHONE);
+ }
+
+ @Test
+ public void testGetBatteryPercentage_usesHotspotNetworkData() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ assertThat(entry.getBatteryPercentage()).isEqualTo(100);
+ }
+
+ @Test
+ public void testConnect_serviceCalled() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ entry.connect(null);
+ verify(mMockSharedConnectivityManager).connectHotspotNetwork(TEST_HOTSPOT_NETWORK_DATA);
+ }
+
+ @Test
+ public void testConnect_nullManager_failureCallback() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, /* sharedConnectivityManager= */ null, TEST_HOTSPOT_NETWORK_DATA);
+
+ entry.setListener(mMockListener);
+ entry.connect(mMockConnectCallback);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback)
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+ }
+
+ @Test
+ public void testConnect_onConnectionStatusChanged_failureCallback() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ entry.setListener(mMockListener);
+ entry.connect(mMockConnectCallback);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, never()).onConnectResult(anyInt());
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN_ERROR);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, times(1))
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_PROVISIONING_FAILED);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, times(2))
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, times(3))
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_UNSUPPORTED);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, times(4))
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_NO_CELL_DATA);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, times(5))
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, times(6))
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, times(7))
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+
+ entry.onConnectionStatusChanged(
+ HotspotNetworkConnectionStatus.CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, times(8))
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+ }
+
+ @Test
+ public void testDisconnect_serviceCalled() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_HOTSPOT_NETWORK_DATA);
+
+ entry.disconnect(null);
+ verify(mMockSharedConnectivityManager).disconnectHotspotNetwork(TEST_HOTSPOT_NETWORK_DATA);
+ }
+
+ @Test
+ public void testDisconnect_nullManager_failureCallback() {
+ final HotspotNetworkEntry entry = new HotspotNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ mMockWifiManager, /* sharedConnectivityManager= */ null, TEST_HOTSPOT_NETWORK_DATA);
+
+ entry.setListener(mMockListener);
+ entry.disconnect(mMockDisconnectCallback);
+ mTestLooper.dispatchAll();
+ verify(mMockDisconnectCallback)
+ .onDisconnectResult(WifiEntry.DisconnectCallback.DISCONNECT_STATUS_FAILURE_UNKNOWN);
+ }
+}
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/KnownNetworkEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/KnownNetworkEntryTest.java
new file mode 100644
index 000000000..8e33fb8bd
--- /dev/null
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/KnownNetworkEntryTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wifitrackerlib;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
+
+import static com.android.wifitrackerlib.StandardWifiEntry.ssidAndSecurityTypeToStandardWifiEntryKey;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.wifi.WifiManager;
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
+import android.os.Handler;
+import android.os.test.TestLooper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class KnownNetworkEntryTest {
+ @Mock private WifiEntry.WifiEntryCallback mMockListener;
+ @Mock private WifiEntry.ConnectCallback mMockConnectCallback;
+ @Mock private WifiTrackerInjector mMockInjector;
+ @Mock private Context mMockContext;
+ @Mock private WifiManager mMockWifiManager;
+ @Mock private SharedConnectivityManager mMockSharedConnectivityManager;
+
+ private TestLooper mTestLooper;
+ private Handler mTestHandler;
+
+ private static final KnownNetwork TEST_KNOWN_NETWORK_DATA = new KnownNetwork.Builder()
+ .setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
+ .setSsid("ssid")
+ .addSecurityType(SECURITY_TYPE_PSK)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .build();
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mTestLooper = new TestLooper();
+ mTestHandler = new Handler(mTestLooper.getLooper());
+
+ when(mMockContext.getString(eq(R.string.wifitrackerlib_known_network_summary), anyString()))
+ .thenAnswer(invocation -> {
+ Object[] args = invocation.getArguments();
+ return "Available from " + args[1];
+ });
+ }
+
+ @Test
+ public void testGetSummary_usesKnownNetworkData() {
+ final KnownNetworkEntry entry = new KnownNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_KNOWN_NETWORK_DATA);
+
+ assertThat(entry.getSummary()).isEqualTo("Available from My Phone");
+ }
+
+ @Test
+ public void testConnect_serviceCalled() {
+ final KnownNetworkEntry entry = new KnownNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_KNOWN_NETWORK_DATA);
+
+ entry.connect(null);
+ verify(mMockSharedConnectivityManager).connectKnownNetwork(TEST_KNOWN_NETWORK_DATA);
+ }
+
+ @Test
+ public void testConnect_nullManager_failureCallback() {
+ final KnownNetworkEntry entry = new KnownNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
+ mMockWifiManager, /* sharedConnectivityManager= */ null, TEST_KNOWN_NETWORK_DATA);
+
+ entry.setListener(mMockListener);
+ entry.connect(mMockConnectCallback);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback)
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+ }
+
+ @Test
+ public void testConnect_onConnectionStatusChanged_failureCallback() {
+ final KnownNetworkEntry entry = new KnownNetworkEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
+ mMockWifiManager, mMockSharedConnectivityManager, TEST_KNOWN_NETWORK_DATA);
+
+ entry.setListener(mMockListener);
+ entry.connect(mMockConnectCallback);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback, never()).onConnectResult(anyInt());
+
+ entry.onConnectionStatusChanged(KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED);
+ mTestLooper.dispatchAll();
+ verify(mMockConnectCallback)
+ .onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+ }
+}
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/MergedCarrierEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/MergedCarrierEntryTest.java
index 63cb86267..d8c257884 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/MergedCarrierEntryTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/MergedCarrierEntryTest.java
@@ -23,7 +23,8 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
-import android.net.NetworkInfo;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -40,7 +41,8 @@ public class MergedCarrierEntryTest {
@Mock private WifiEntry.ConnectCallback mMockConnectCallback;
@Mock private WifiManager mMockWifiManager;
@Mock private WifiInfo mMockWifiInfo;
- @Mock private NetworkInfo mMockNetworkInfo;
+ @Mock private Network mMockNetwork;
+ @Mock private NetworkCapabilities mMockNetworkCapabilities;
@Mock private Context mMockContext;
@Mock private Resources mMockResources;
@@ -52,8 +54,8 @@ public class MergedCarrierEntryTest {
MockitoAnnotations.initMocks(this);
when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(
- NetworkInfo.DetailedState.DISCONNECTED);
+ when(mMockWifiInfo.isPrimary()).thenReturn(true);
+ when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
mTestLooper = new TestLooper();
mTestHandler = new Handler(mTestLooper.getLooper());
when(mMockContext.getMainLooper()).thenReturn(Looper.getMainLooper());
@@ -70,9 +72,8 @@ public class MergedCarrierEntryTest {
false, mMockContext, subId);
when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- entry.updateConnectionInfo(mMockWifiInfo, mMockNetworkInfo);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_CONNECTED);
}
@@ -127,9 +128,8 @@ public class MergedCarrierEntryTest {
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
final String ssid = "ssid";
when(mMockWifiInfo.getSSID()).thenReturn("\"" + ssid + "\"");
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- entry.updateConnectionInfo(mMockWifiInfo, mMockNetworkInfo);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSsid()).isEqualTo(ssid);
}
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NetworkDetailsTrackerTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NetworkDetailsTrackerTest.java
index 1225b4c04..ff4cec1c7 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NetworkDetailsTrackerTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NetworkDetailsTrackerTest.java
@@ -27,7 +27,10 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
import android.os.Handler;
import android.os.test.TestLooper;
@@ -111,4 +114,28 @@ public class NetworkDetailsTrackerTest {
Collections.singletonList(WifiEntry.SECURITY_NONE))).toString());
assertThat(tracker).isInstanceOf(StandardNetworkDetailsTracker.class);
}
+
+ /**
+ * Tests that createNetworkDetailsTracker() returns a HotspotNetworkDetailsTracker if a
+ * HotspotNetworkEntry key is passed in.
+ */
+ @Test
+ public void testCreateNetworkDetailsTracker_returnsHotspotNetworkDetailsTracker()
+ throws Exception {
+ final NetworkDetailsTracker tracker = createTestNetworkDetailsTracker(
+ new HotspotNetworkEntry.HotspotNetworkEntryKey(new HotspotNetwork.Builder()
+ .setDeviceId(1)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("Phone", "Pixel")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3).build())
+ .setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
+ .setNetworkName("Google Fi")
+ .setHotspotSsid("SSID")
+ .setHotspotBssid("BSSID")
+ .addHotspotSecurityType(WifiInfo.SECURITY_TYPE_WEP)
+ .build()).toString());
+ assertThat(tracker).isInstanceOf(HotspotNetworkDetailsTracker.class);
+ }
}
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NonSdkApiWrapperTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NonSdkApiWrapperTest.java
index 1d68b18ee..b0b1449d8 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NonSdkApiWrapperTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/NonSdkApiWrapperTest.java
@@ -74,22 +74,22 @@ public class NonSdkApiWrapperTest {
}
/**
- * Verifies the functionality of {@link NonSdkApiWrapper#isVcnOverWifi}
+ * Verifies the functionality of {@link NonSdkApiWrapper#getVcnWifiInfo(NetworkCapabilities)}
*/
@Test
- public void testIsVcnOverWifi() {
+ public void testGetVcnWifiInfo() {
NetworkCapabilities networkCapabilities = mock(NetworkCapabilities.class);
- assertThat(NonSdkApiWrapper.isVcnOverWifi(networkCapabilities)).isFalse();
+ assertThat(NonSdkApiWrapper.getVcnWifiInfo(networkCapabilities)).isNull();
VcnTransportInfo vcnTransportInfo = mock(VcnTransportInfo.class);
when(networkCapabilities.getTransportInfo()).thenReturn(vcnTransportInfo);
- assertThat(NonSdkApiWrapper.isVcnOverWifi(networkCapabilities)).isFalse();
+ assertThat(NonSdkApiWrapper.getVcnWifiInfo(networkCapabilities)).isNull();
WifiInfo wifiInfo = mock(WifiInfo.class);
when(vcnTransportInfo.getWifiInfo()).thenReturn(wifiInfo);
- assertThat(NonSdkApiWrapper.isVcnOverWifi(networkCapabilities)).isTrue();
+ assertThat(NonSdkApiWrapper.getVcnWifiInfo(networkCapabilities)).isEqualTo(wifiInfo);
}
}
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java
index 6eeff5888..ebd86cb02 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java
@@ -31,8 +31,8 @@ import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
+import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -45,6 +45,7 @@ import android.os.test.TestLooper;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
@@ -56,7 +57,8 @@ public class PasspointWifiEntryTest {
@Mock private WifiManager mMockWifiManager;
@Mock private Resources mMockResources;
@Mock private WifiInfo mMockWifiInfo;
- @Mock private NetworkInfo mMockNetworkInfo;
+ @Mock private Network mMockNetwork;
+ @Mock private NetworkCapabilities mMockNetworkCapabilities;
@Mock private ConnectivityManager mMockConnectivityManager;
private TestLooper mTestLooper;
@@ -71,12 +73,15 @@ public class PasspointWifiEntryTest {
mTestLooper = new TestLooper();
mTestHandler = new Handler(mTestLooper.getLooper());
+ when(mMockWifiInfo.isPrimary()).thenReturn(true);
when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(
- NetworkInfo.DetailedState.DISCONNECTED);
+ when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator)).thenReturn("/");
+
+ when(mMockContext.getSystemService(ConnectivityManager.class))
+ .thenReturn(mMockConnectivityManager);
}
@Test
@@ -135,29 +140,20 @@ public class PasspointWifiEntryTest {
String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
- when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
- ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mockConnectivityManager);
- final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
- WifiInfo wifiInfo = mock(WifiInfo.class);
- when(wifiInfo.isPasspointAp()).thenReturn(true);
- when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
- NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+ when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+ when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mMockContext, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- entry.updateNetworkCapabilities(networkCapabilities);
- entry.setIsDefaultNetwork(true);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ entry.onDefaultNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSummary()).isEqualTo("Connected");
}
@@ -168,42 +164,29 @@ public class PasspointWifiEntryTest {
String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
- when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
- ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mockConnectivityManager);
- final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
- WifiInfo wifiInfo = mock(WifiInfo.class);
- when(wifiInfo.isPasspointAp()).thenReturn(true);
- when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
- NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+ when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+ when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mMockContext, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- entry.updateNetworkCapabilities(networkCapabilities);
- entry.setIsDefaultNetwork(false);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSummary()).isEqualTo("");
}
@Test
public void testGetSecurityTypes_connectedWifiNetwork_showsCurrentSecurityType() {
- WifiInfo wifiInfo = mock(WifiInfo.class);
- when(wifiInfo.isPasspointAp()).thenReturn(true);
- when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
- when(wifiInfo.getCurrentSecurityType()).thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
- NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+ when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+ when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+ when(mMockWifiInfo.getCurrentSecurityType())
+ .thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mMockContext, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
@@ -213,13 +196,14 @@ public class PasspointWifiEntryTest {
WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2,
WifiInfo.SECURITY_TYPE_PASSPOINT_R3));
- entry.updateConnectionInfo(wifiInfo, networkInfo);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSecurityTypes())
.containsExactly(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
- when(wifiInfo.getCurrentSecurityType()).thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
- entry.updateConnectionInfo(wifiInfo, networkInfo);
+ when(mMockWifiInfo.getCurrentSecurityType())
+ .thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSecurityTypes()).containsExactly(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
}
@@ -239,18 +223,9 @@ public class PasspointWifiEntryTest {
}
@Test
- public void testShouldShowXLevelIcon_unvalidatedOrNotDefault_returnsTrue() {
- ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mockConnectivityManager);
- final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
- WifiInfo wifiInfo = mock(WifiInfo.class);
- when(wifiInfo.isPasspointAp()).thenReturn(true);
- when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
- final NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+ public void testShouldShowXLevelIcon_unvalidatedOrLowQuality_returnsTrue() {
+ when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+ when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mMockContext, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
@@ -259,31 +234,27 @@ public class PasspointWifiEntryTest {
// Disconnected should return false;
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
- // Not validated, Not Default
- entry.updateConnectionInfo(wifiInfo, networkInfo);
-
- // Validation attempt not complete, should not show X level icon yet.
+ // Connected but validation attempt not complete, should not show X level icon yet.
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
- // Validation attempt complete, should show X level icon now.
+ // Validation attempt complete, should show X level icon.
ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport = mock(
ConnectivityDiagnosticsManager.ConnectivityReport.class);
+ when(connectivityReport.getNetwork()).thenReturn(mMockNetwork);
entry.updateConnectivityReport(connectivityReport);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
- // Not Validated, Default
- entry.setIsDefaultNetwork(true);
-
- assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
-
- // Validated, Default
- entry.updateNetworkCapabilities(networkCapabilities);
-
+ // Internet validated, should not show X level icon.
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
- // Validated, Not Default
- entry.setIsDefaultNetwork(false);
-
+ // Cell becomes default (i.e. low quality wifi), show X level icon.
+ entry.onDefaultNetworkCapabilitiesChanged(Mockito.mock(Network.class),
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
}
@@ -296,18 +267,14 @@ public class PasspointWifiEntryTest {
config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
config.FQDN = FQDN;
when(mMockWifiManager.getFactoryMacAddresses()).thenReturn(new String[]{factoryMac});
- WifiInfo wifiInfo = mock(WifiInfo.class);
- when(wifiInfo.isPasspointAp()).thenReturn(true);
- when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
- when(wifiInfo.getMacAddress()).thenReturn(wifiInfoMac);
- NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+ when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+ when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+ when(mMockWifiInfo.getMacAddress()).thenReturn(wifiInfoMac);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mMockContext, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
- entry.updateConnectionInfo(wifiInfo, networkInfo);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getMacAddress()).isEqualTo(wifiInfoMac);
}
@@ -329,34 +296,36 @@ public class PasspointWifiEntryTest {
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
- NetworkCapabilities captivePortalCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL).build();
- entry.updateNetworkCapabilities(captivePortalCapabilities);
+ when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+ when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+ when(mMockNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.canSignIn()).isTrue();
}
@Test
public void testUpdateNetworkCapabilities_userConnect_autoOpenCaptivePortalOnce() {
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mMockConnectivityManager);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mMockContext, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
- NetworkCapabilities captivePortalCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL).build();
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
// Simulate user tapping on the network and receiving captive portal capabilities.
// This should trigger the captive portal app.
entry.connect(null /* callback */);
- entry.updateNetworkCapabilities(captivePortalCapabilities);
+ when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+ when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+ when(mMockNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
// Update network capabilities again. This should not trigger the captive portal app.
- entry.updateNetworkCapabilities(captivePortalCapabilities);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
} finally {
@@ -371,27 +340,18 @@ public class PasspointWifiEntryTest {
String summarySeparator = " / ";
String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
- when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
- ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mockConnectivityManager);
- final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
- WifiInfo wifiInfo = mock(WifiInfo.class);
- when(wifiInfo.isPasspointAp()).thenReturn(true);
- when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
- NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+ when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+ when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mMockContext, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- entry.updateNetworkCapabilities(networkCapabilities);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
// Disconnect the entry before it can be updated with scans and a WifiConfiguration
entry.disconnect(null);
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/SavedNetworkTrackerTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/SavedNetworkTrackerTest.java
index 798a6b960..c3880a47c 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/SavedNetworkTrackerTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/SavedNetworkTrackerTest.java
@@ -16,13 +16,22 @@
package com.android.wifitrackerlib;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.wifitrackerlib.TestUtils.GOOD_RSSI;
import static com.android.wifitrackerlib.TestUtils.buildScanResult;
import static com.android.wifitrackerlib.TestUtils.buildWifiConfiguration;
+import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -31,9 +40,12 @@ import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.hotspot2.PasspointConfiguration;
@@ -48,7 +60,9 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
import java.time.Clock;
import java.util.ArrayList;
@@ -64,6 +78,8 @@ public class SavedNetworkTrackerTest {
private static final long MAX_SCAN_AGE_MILLIS = 15_000;
private static final long SCAN_INTERVAL_MILLIS = 10_000;
+ private static final String TEST_CACERT_NOT_REQUIRED_ALIAS = "cacert_not_required";
+
@Mock private WifiTrackerInjector mInjector;
@Mock private Lifecycle mMockLifecycle;
@Mock private Context mMockContext;
@@ -73,10 +89,17 @@ public class SavedNetworkTrackerTest {
@Mock private Clock mMockClock;
@Mock private SavedNetworkTracker.SavedNetworkTrackerCallback mMockCallback;
@Mock private WifiInfo mMockWifiInfo;
- @Mock private NetworkInfo mMockNetworkInfo;
+ @Mock private Network mMockNetwork;
+ @Mock private NetworkCapabilities mMockNetworkCapabilities;
+ @Mock private LinkProperties mMockLinkProperties;
private TestLooper mTestLooper;
+ private final ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
+ ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+ private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
+ mDefaultNetworkCallbackCaptor =
+ ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
private final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
@@ -108,7 +131,23 @@ public class SavedNetworkTrackerTest {
when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true);
when(mMockWifiManager.isWpa3SuiteBSupported()).thenReturn(true);
when(mMockWifiManager.isEnhancedOpenSupported()).thenReturn(true);
- when(mMockConnectivityManager.getNetworkInfo(any())).thenReturn(mMockNetworkInfo);
+ when(mMockWifiManager.getCurrentNetwork()).thenReturn(mMockNetwork);
+ when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
+ when(mMockWifiInfo.isPrimary()).thenReturn(true);
+ when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
+ when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
+ when(mMockWifiInfo.makeCopy(anyLong())).thenReturn(mMockWifiInfo);
+ when(mMockNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
+ .thenReturn(true);
+ when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
+ // A real NetworkCapabilities is needed here in order to create a copy (with location info)
+ // using the NetworkCapabilities constructor in handleOnStart.
+ when(mMockConnectivityManager.getNetworkCapabilities(mMockNetwork))
+ .thenReturn(new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build());
+ when(mMockConnectivityManager.getLinkProperties(mMockNetwork))
+ .thenReturn(mMockLinkProperties);
when(mMockContext.getSystemService(ConnectivityDiagnosticsManager.class))
.thenReturn(mMockConnectivityDiagnosticsManager);
when(mMockClock.millis()).thenReturn(START_MILLIS);
@@ -194,7 +233,6 @@ public class SavedNetworkTrackerTest {
any(), any(), any());
assertThat(savedNetworkTracker.getSavedWifiEntries().stream()
- .filter(entry -> entry.mForSavedNetworksPage)
.map(WifiEntry::getTitle)
.collect(Collectors.toSet()))
.containsExactly("ssid0", "ssid1", "ssid2");
@@ -275,6 +313,7 @@ public class SavedNetworkTrackerTest {
public void testGetSavedWifiEntries_scanResultsAvailableAction_changesLevel() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = buildWifiConfiguration("ssid");
+ config.networkId = 1;
when(mMockWifiManager.getConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
savedNetworkTracker.onStart();
@@ -437,13 +476,12 @@ public class SavedNetworkTrackerTest {
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
WifiEntry entry = savedNetworkTracker.getSavedWifiEntries().get(0);
- assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_CONNECTED);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
}
/**
@@ -462,20 +500,18 @@ public class SavedNetworkTrackerTest {
buildScanResult("ssid", "bssid", START_MILLIS)));
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
final WifiEntry entry = savedNetworkTracker.getSavedWifiEntries().get(0);
assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)
- .putExtra(WifiManager.EXTRA_NETWORK_INFO, mMockNetworkInfo));
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
- assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_CONNECTED);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
}
/**
@@ -494,22 +530,183 @@ public class SavedNetworkTrackerTest {
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
final WifiEntry entry = savedNetworkTracker.getSavedWifiEntries().get(0);
- assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_CONNECTED);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
- when(mMockNetworkInfo.getDetailedState())
- .thenReturn(NetworkInfo.DetailedState.DISCONNECTED);
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)
- .putExtra(WifiManager.EXTRA_NETWORK_INFO, mMockNetworkInfo));
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+ }
+
+ /**
+ * Tests that getConnectedEntry() will return the correct primary network after an MBB sequence.
+ */
+ @Test
+ public void testConnectedEntry_mbbFlow_matchesNewPrimary() {
+ final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ final WifiConfiguration mbbConfig = new WifiConfiguration();
+ mbbConfig.SSID = "\"otherSsid\"";
+ mbbConfig.networkId = 2;
+ when(mMockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(config, mbbConfig));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(config.networkId);
+ when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
+ savedNetworkTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
+
+ // Start off connected
+ List<WifiEntry> savedEntries = savedNetworkTracker.getSavedWifiEntries();
+ assertThat(savedEntries.size()).isEqualTo(2);
+ WifiEntry originalEntry = null;
+ WifiEntry mbbEntry = null;
+ for (WifiEntry entry : savedNetworkTracker.getSavedWifiEntries()) {
+ if (entry.getTitle().equals("ssid")) {
+ originalEntry = entry;
+ } else if (entry.getTitle().equals("otherSsid")) {
+ mbbEntry = entry;
+ }
+ }
+ assertThat(originalEntry).isNotNull();
+ assertThat(originalEntry.getConnectedState())
+ .isEqualTo(CONNECTED_STATE_CONNECTED);
+ assertThat(mbbEntry).isNotNull();
+ assertThat(mbbEntry.getConnectedState())
+ .isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+
+ MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
+ try {
+ // MBB network connected but not primary yet.
+ Network mbbNetwork = mock(Network.class);
+ NetworkCapabilities mbbNetworkCapabilities = mock(NetworkCapabilities.class);
+ WifiInfo mbbWifiInfo = mock(WifiInfo.class);
+ when(mbbWifiInfo.getNetworkId()).thenReturn(mbbConfig.networkId);
+ when(mbbWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
+ when(mbbNetworkCapabilities.getTransportInfo()).thenReturn(mbbWifiInfo);
+ doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(mbbWifiInfo));
+ mNetworkCallbackCaptor.getValue()
+ .onCapabilitiesChanged(mbbNetwork, mbbNetworkCapabilities);
+ // Original network should still be connected.
+ assertThat(originalEntry.getConnectedState())
+ .isEqualTo(CONNECTED_STATE_CONNECTED);
+ assertThat(mbbEntry.getConnectedState())
+ .isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+
+ // Original network becomes non-primary and MBB network becomes primary.
+ doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(mMockWifiInfo));
+ mNetworkCallbackCaptor.getValue()
+ .onCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(mbbWifiInfo));
+ mNetworkCallbackCaptor.getValue()
+ .onCapabilitiesChanged(mbbNetwork, mbbNetworkCapabilities);
+ // MBB network should be connected now.
+ assertThat(originalEntry.getConnectedState())
+ .isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+ assertThat(mbbEntry.getConnectedState())
+ .isEqualTo(CONNECTED_STATE_CONNECTED);
+
+ // Original network is lost. MBB network should still be connected
+ assertThat(originalEntry.getConnectedState())
+ .isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+ assertThat(mbbEntry.getConnectedState())
+ .isEqualTo(CONNECTED_STATE_CONNECTED);
+ } finally {
+ session.finishMocking();
+ }
+ }
+
+ @Test
+ public void testCertificateRequired() throws Exception {
+ final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
+
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
+ when(mMockWifiManager.getConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
+ buildScanResult("ssid", "bssid", START_MILLIS)));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(-50);
+ savedNetworkTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ any(), any(), any());
+
+ // Check another CA cert alias.
+ assertFalse(savedNetworkTracker.isCertificateRequired(TEST_CACERT_NOT_REQUIRED_ALIAS));
+ assertEquals(0, savedNetworkTracker
+ .getCertificateRequesterNames(TEST_CACERT_NOT_REQUIRED_ALIAS).size());
+ }
+
+ /**
+ * Tests that a connected WifiEntry's isDefaultNetwork() will reflect updates from the default
+ * network changing.
+ */
+ @Test
+ public void testGetConnectedEntry_defaultNetworkChanges_isDefaultNetworkChanges() {
+ final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ when(mMockWifiManager.getConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
+ buildScanResult("ssid", "bssid", START_MILLIS)));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(-50);
+ savedNetworkTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockConnectivityManager)
+ .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
+ verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
+ mDefaultNetworkCallbackCaptor.capture(), any());
+ verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
+ mDefaultNetworkCallbackCaptor.capture(), any());
+
+ WifiEntry connectedWifiEntry = savedNetworkTracker.getSavedWifiEntries().get(0);
+ assertThat(connectedWifiEntry).isNotNull();
+ assertThat(connectedWifiEntry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
+
+ // No default
+ assertThat(connectedWifiEntry.isDefaultNetwork()).isFalse();
+
+ // Cell is default
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(Mockito.mock(Network.class),
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
+ assertThat(connectedWifiEntry.isDefaultNetwork()).isFalse();
+
+ // Other Wi-Fi network is default
+ Network otherWifiNetwork = mock(Network.class);
+ WifiInfo otherWifiInfo = mock(WifiInfo.class);
+ when(otherWifiInfo.getNetworkId()).thenReturn(2);
+ NetworkCapabilities otherNetworkCapabilities = mock(NetworkCapabilities.class);
+ when(otherNetworkCapabilities.getTransportInfo()).thenReturn(otherWifiInfo);
+ when(otherNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
+ .thenReturn(true);
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(otherWifiNetwork,
+ otherNetworkCapabilities);
+ assertThat(connectedWifiEntry.isDefaultNetwork()).isFalse();
+
+ // This Wi-Fi network is default
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
+ mMockNetworkCapabilities);
+ assertThat(connectedWifiEntry.isDefaultNetwork()).isTrue();
+
+ // Lose the default network
+ mDefaultNetworkCallbackCaptor.getValue().onLost(mock(Network.class));
+ assertThat(connectedWifiEntry.isDefaultNetwork()).isFalse();
}
}
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardNetworkDetailsTrackerTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardNetworkDetailsTrackerTest.java
index 23fbc45a9..8bac4f8d3 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardNetworkDetailsTrackerTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardNetworkDetailsTrackerTest.java
@@ -20,6 +20,9 @@ import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
import static com.android.wifitrackerlib.StandardWifiEntry.StandardWifiEntryKey;
import static com.android.wifitrackerlib.StandardWifiEntry.ssidAndSecurityTypeToStandardWifiEntryKey;
+import static com.android.wifitrackerlib.TestUtils.BAD_LEVEL;
+import static com.android.wifitrackerlib.TestUtils.BAD_RSSI;
+import static com.android.wifitrackerlib.TestUtils.GOOD_RSSI;
import static com.android.wifitrackerlib.TestUtils.buildScanResult;
import static com.android.wifitrackerlib.TestUtils.buildWifiConfiguration;
import static com.android.wifitrackerlib.WifiEntry.SECURITY_NONE;
@@ -28,6 +31,7 @@ import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -40,6 +44,7 @@ import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiScanner;
import android.os.Handler;
import android.os.test.TestLooper;
@@ -66,6 +71,7 @@ public class StandardNetworkDetailsTrackerTest {
@Mock private Lifecycle mMockLifecycle;
@Mock private Context mMockContext;
@Mock private WifiManager mMockWifiManager;
+ @Mock private WifiScanner mWifiScanner;
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private ConnectivityDiagnosticsManager mMockConnectivityDiagnosticsManager;
@Mock private Clock mMockClock;
@@ -104,8 +110,15 @@ public class StandardNetworkDetailsTrackerTest {
when(mMockWifiManager.isEnhancedOpenSupported()).thenReturn(true);
when(mMockWifiManager.getScanResults()).thenReturn(new ArrayList<>());
when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
+ when(mMockWifiManager.calculateSignalLevel(TestUtils.GOOD_RSSI))
+ .thenReturn(TestUtils.GOOD_LEVEL);
+ when(mMockWifiManager.calculateSignalLevel(TestUtils.OKAY_RSSI))
+ .thenReturn(TestUtils.OKAY_LEVEL);
+ when(mMockWifiManager.calculateSignalLevel(TestUtils.BAD_RSSI))
+ .thenReturn(TestUtils.BAD_LEVEL);
when(mMockContext.getSystemService(ConnectivityDiagnosticsManager.class))
.thenReturn(mMockConnectivityDiagnosticsManager);
+ when(mMockContext.getSystemService(WifiScanner.class)).thenReturn(mWifiScanner);
when(mMockClock.millis()).thenReturn(START_MILLIS);
}
@@ -127,26 +140,6 @@ public class StandardNetworkDetailsTrackerTest {
* Tests that SCAN_RESULTS_AVAILABLE_ACTION updates the level of the entry.
*/
@Test
- public void testHandleOnStart_scanResultUpdaterUpdateCorrectly() throws Exception {
- final StandardWifiEntryKey key =
- ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_NONE);
- final StandardNetworkDetailsTracker tracker =
- createTestStandardNetworkDetailsTracker(key.toString());
- final ScanResult other = buildScanResult("ssid2", "bssid", START_MILLIS, -50 /* rssi */);
- when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(other));
-
- //tracker.onStart();
- tracker.handleOnStart();
-
- final long invalidCount = tracker.mScanResultUpdater.getScanResults().stream().filter(
- scanResult -> !"ssid".equals(scanResult.SSID)).count();
- assertThat(invalidCount).isEqualTo(0);
- }
-
- /**
- * Tests that SCAN_RESULTS_AVAILABLE_ACTION updates the level of the entry.
- */
- @Test
public void testScanResultsAvailableAction_updates_getLevel() throws Exception {
// Starting without any scans available should make level WIFI_LEVEL_UNREACHABLE
final ScanResult scan = buildScanResult("ssid", "bssid", START_MILLIS, -50 /* rssi */);
@@ -271,7 +264,6 @@ public class StandardNetworkDetailsTrackerTest {
// WifiEntry should correspond to the saved config
WifiEntry wifiEntry = tracker.getWifiEntry();
-// assertThat(wifiEntry.getSecurityTypes().size()).isEqualTo(1);
assertThat(wifiEntry.getSecurityTypes().get(0)).isEqualTo(WifiInfo.SECURITY_TYPE_SAE);
assertThat(wifiEntry.getLevel()).isEqualTo(WIFI_LEVEL_UNREACHABLE);
@@ -284,9 +276,42 @@ public class StandardNetworkDetailsTrackerTest {
// WifiEntry should correspond to the unsaved scan
wifiEntry = tracker.getWifiEntry();
-// assertThat(wifiEntry.getSecurityTypes().size()).isEqualTo(1);
assertThat(wifiEntry.getSecurityTypes().get(0)).isEqualTo(SECURITY_TYPE_PSK);
assertThat(wifiEntry.getLevel()).isNotEqualTo(WIFI_LEVEL_UNREACHABLE);
+ }
+
+ /**
+ * Tests that we update the chosen entry's ScanResults correctly after a WifiScanner scan.
+ */
+ @Test
+ public void testScanner_wifiScannerResultReceived_scanResultsUpdated() {
+ final String ssid = "ssid";
+ final WifiConfiguration config = buildWifiConfiguration(ssid);
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ StandardNetworkDetailsTracker tracker = createTestStandardNetworkDetailsTracker(
+ ssidAndSecurityTypeToStandardWifiEntryKey(ssid, SECURITY_NONE).toString());
+ tracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ any(), any(), any());
+ mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
+ new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION).putExtra(
+ WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
+ ArgumentCaptor<WifiScanner.ScanListener> mScanListenerCaptor =
+ ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
+ verify(mWifiScanner).startScan(any(), mScanListenerCaptor.capture());
+ ScanResult[] scanResults = new ScanResult[]{
+ buildScanResult(ssid, "bssid", START_MILLIS, BAD_RSSI),
+ buildScanResult("different ssid", "bssid", START_MILLIS, GOOD_RSSI),
+ };
+ WifiScanner.ScanData scanData = mock(WifiScanner.ScanData.class);
+ when(scanData.getResults()).thenReturn(scanResults);
+
+ mScanListenerCaptor.getValue().onResults(new WifiScanner.ScanData[]{scanData});
+ mTestLooper.dispatchAll();
+ // Updated with the correct SSID and ignored the different SSID.
+ assertThat(tracker.getWifiEntry().getLevel()).isEqualTo(BAD_LEVEL);
}
}
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
index 8ae5a51e1..609b00c31 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
@@ -19,8 +19,9 @@ package com.android.wifitrackerlib;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD;
+import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES;
+import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED;
-import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_OPEN;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_OWE;
@@ -36,14 +37,12 @@ import static com.android.wifitrackerlib.StandardWifiEntry.ssidAndSecurityTypeTo
import static com.android.wifitrackerlib.TestUtils.buildScanResult;
import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_DISCONNECTED;
-import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -59,8 +58,8 @@ import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.MacAddress;
+import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
@@ -79,10 +78,13 @@ import android.util.ArraySet;
import androidx.core.os.BuildCompat;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
@@ -97,7 +99,8 @@ public class StandardWifiEntryTest {
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private SubscriptionManager mSubscriptionManager;
@Mock private WifiInfo mMockWifiInfo;
- @Mock private NetworkInfo mMockNetworkInfo;
+ @Mock private Network mMockNetwork;
+ @Mock private NetworkCapabilities mMockNetworkCapabilities;
@Mock private WifiTrackerInjector mMockInjector;
@Mock private Context mMockContext;
@Mock private Resources mMockResources;
@@ -117,10 +120,10 @@ public class StandardWifiEntryTest {
mTestLooper = new TestLooper();
mTestHandler = new Handler(mTestLooper.getLooper());
+ when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
+ when(mMockWifiInfo.isPrimary()).thenReturn(true);
when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(
- NetworkInfo.DetailedState.DISCONNECTED);
when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true);
when(mMockWifiManager.isEnhancedOpenSupported()).thenReturn(true);
when(mMockWifiManager.isWpa3SuiteBSupported()).thenReturn(true);
@@ -132,6 +135,8 @@ public class StandardWifiEntryTest {
.thenReturn(TestUtils.BAD_LEVEL);
when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockContext.getSystemService(ConnectivityManager.class))
+ .thenReturn(mMockConnectivityManager);
when(mMockContext.getSystemService(SubscriptionManager.class))
.thenReturn(mSubscriptionManager);
when(mMockContext.getSystemService(DevicePolicyManager.class))
@@ -371,7 +376,7 @@ public class StandardWifiEntryTest {
}
@Test
- public void testUpdateConnectionInfo_matchingNetId_updatesConnectionInfo() {
+ public void testOnNetworkCapabilitiesChanged_matchingNetworkId_becomesConnected() {
final WifiConfiguration config = new WifiConfiguration();
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
config.SSID = "\"ssid\"";
@@ -381,18 +386,21 @@ public class StandardWifiEntryTest {
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_EAP),
Collections.singletonList(config), null, mMockWifiManager,
false /* forSavedNetworksPage */);
- when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- entry.updateConnectionInfo(mMockWifiInfo, mMockNetworkInfo);
+ // Ignore non-matching network id
+ when(mMockWifiInfo.getNetworkId()).thenReturn(2);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_DISCONNECTED);
- assertThat(entry.getLevel()).isEqualTo(TestUtils.GOOD_LEVEL);
+ // Matching network id should result in connected
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
}
@Test
- public void testUpdateConnectionInfo_nonMatchingNetId_doesNotUpdateConnectionInfo() {
+ public void testOnNetworkLost_matchingNetwork_becomesDisconnected() {
final WifiConfiguration config = new WifiConfiguration();
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
config.SSID = "\"ssid\"";
@@ -402,17 +410,80 @@ public class StandardWifiEntryTest {
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_EAP),
Collections.singletonList(config), null, mMockWifiManager,
false /* forSavedNetworksPage */);
- when(mMockWifiInfo.getNetworkId()).thenReturn(2);
- when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+
+ // Non-matching network loss should be ignored
+ entry.onNetworkLost(mock(Network.class));
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
+
+ // Matching network loss should result in disconnected
+ entry.onNetworkLost(mMockNetwork);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_DISCONNECTED);
+ }
+
+ @Test
+ public void testOnNetworkCapabilitiesChanged_notPrimaryAnymore_becomesDisconnected() {
+ final WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ final StandardWifiEntry entry = new StandardWifiEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_EAP),
+ Collections.singletonList(config), null, mMockWifiManager,
+ false /* forSavedNetworksPage */);
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
- entry.updateConnectionInfo(mMockWifiInfo, mMockNetworkInfo);
+ MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
+ try {
+ ExtendedMockito.doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(any()));
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ } finally {
+ session.finishMocking();
+ }
- assertThat(entry.getLevel()).isEqualTo(WIFI_LEVEL_UNREACHABLE);
assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_DISCONNECTED);
}
@Test
+ public void testOnNetworkCapabilitiesChanged_nonPrimaryOem_becomesConnected() {
+ final WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ final StandardWifiEntry entry = new StandardWifiEntry(
+ mMockInjector, mMockContext, mTestHandler,
+ ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_EAP),
+ Collections.singletonList(config), null, mMockWifiManager,
+ false /* forSavedNetworksPage */);
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
+
+ MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
+ try {
+ ExtendedMockito.doReturn(false)
+ .when(() -> NonSdkApiWrapper.isPrimary(mMockWifiInfo));
+ // Is OEM
+ ExtendedMockito.doReturn(true)
+ .when(() -> NonSdkApiWrapper.isOemCapabilities(mMockNetworkCapabilities));
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
+
+ // Not OEM anymore
+ ExtendedMockito.doReturn(false)
+ .when(() -> NonSdkApiWrapper.isOemCapabilities(mMockNetworkCapabilities));
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_DISCONNECTED);
+ } finally {
+ session.finishMocking();
+ }
+ }
+
+ @Test
public void testConnect_savedNetwork_usesSavedConfig() {
final ScanResult scan = buildScanResult("ssid", "bssid", 0, TestUtils.GOOD_RSSI);
final StandardWifiEntry entry = new StandardWifiEntry(
@@ -534,10 +605,6 @@ public class StandardWifiEntryTest {
final String factoryMac = "01:23:45:67:89:ab";
final String wifiInfoMac = "11:23:45:67:89:ab";
- final NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
-
when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
when(mMockWifiInfo.getMacAddress()).thenReturn(wifiInfoMac);
final WifiConfiguration config = new WifiConfiguration();
@@ -551,7 +618,7 @@ public class StandardWifiEntryTest {
Collections.singletonList(config), null, mMockWifiManager,
false /* forSavedNetworksPage */);
- entry.updateConnectionInfo(mMockWifiInfo, networkInfo);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getMacAddress()).isEqualTo(wifiInfoMac);
}
@@ -650,10 +717,10 @@ public class StandardWifiEntryTest {
false /* forSavedNetworksPage */);
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- entry.updateConnectionInfo(mMockWifiInfo, mMockNetworkInfo);
- entry.updateLinkProperties(new LinkProperties());
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+
+ entry.updateLinkProperties(mMockNetwork, new LinkProperties());
assertThat(entry.getConnectedInfo()).isNotNull();
}
@@ -692,17 +759,8 @@ public class StandardWifiEntryTest {
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
- final ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
- final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mockConnectivityManager);
-
- final WifiInfo wifiInfo = new WifiInfo.Builder().setNetworkId(networkId).build();
- final NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
-
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = networkId;
@@ -712,9 +770,11 @@ public class StandardWifiEntryTest {
Collections.singletonList(config), null, mMockWifiManager,
false /* forSavedNetworksPage */);
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- entry.updateNetworkCapabilities(networkCapabilities);
- entry.setIsDefaultNetwork(true);
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
+
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ entry.onDefaultNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSummary()).isEqualTo("Connected");
}
@@ -730,16 +790,6 @@ public class StandardWifiEntryTest {
.thenReturn(summarySeparator);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
- final ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
- final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mockConnectivityManager);
-
- final WifiInfo wifiInfo = new WifiInfo.Builder().setNetworkId(networkId).build();
- final NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
@@ -749,10 +799,14 @@ public class StandardWifiEntryTest {
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_OPEN),
Collections.singletonList(config), null, mMockWifiManager,
false /* forSavedNetworksPage */);
+ when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
- entry.updateConnectionInfo(wifiInfo, networkInfo);
- entry.updateNetworkCapabilities(networkCapabilities);
- entry.setIsDefaultNetwork(false);
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ Network otherNetwork = mock(Network.class);
+ when(otherNetwork.getNetId()).thenReturn(2);
+ entry.onDefaultNetworkCapabilitiesChanged(otherNetwork, new NetworkCapabilities());
assertThat(entry.getSummary()).isEqualTo("");
}
@@ -760,14 +814,6 @@ public class StandardWifiEntryTest {
@Test
public void testShouldShowXLevelIcon_unvalidatedOrNotDefault_returnsTrue() {
final int networkId = 1;
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mMockConnectivityManager);
- final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
- final WifiInfo wifiInfo = new WifiInfo.Builder().setNetworkId(networkId).build();
- final NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
- networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = networkId;
@@ -781,31 +827,29 @@ public class StandardWifiEntryTest {
// Disconnected should return false;
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
- // Not validated, Not Default
- entry.updateConnectionInfo(wifiInfo, networkInfo);
-
- // Validation attempt not complete, should not show X level icon yet.
+ // Connected but validation attempt not complete, should not show X level icon yet.
+ when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
+ when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
- // Validation attempt complete, should show X level icon now.
+ // Validation attempt complete, should show X level icon.
ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport = mock(
ConnectivityDiagnosticsManager.ConnectivityReport.class);
+ when(connectivityReport.getNetwork()).thenReturn(mMockNetwork);
entry.updateConnectivityReport(connectivityReport);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
- // Not Validated, Default
- entry.setIsDefaultNetwork(true);
-
- assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
-
- // Validated, Default
- entry.updateNetworkCapabilities(networkCapabilities);
-
+ // Internet validated, should not show X level icon.
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
- // Validated, Not Default
- entry.setIsDefaultNetwork(false);
-
+ // Cell becomes default (i.e. low quality wifi), show X level icon.
+ entry.onDefaultNetworkCapabilitiesChanged(Mockito.mock(Network.class),
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
}
@@ -862,7 +906,6 @@ public class StandardWifiEntryTest {
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(TestUtils.GOOD_RSSI);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
StandardWifiEntry entry = new StandardWifiEntry(
mMockInjector, mMockContext, mTestHandler,
@@ -871,14 +914,14 @@ public class StandardWifiEntryTest {
mMockWifiManager, false /* forSavedNetworksPage */);
when(mMockWifiInfo.getCurrentSecurityType()).thenReturn(SECURITY_TYPE_PSK);
- entry.updateConnectionInfo(mMockWifiInfo, mMockNetworkInfo);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
// Both PSK and SAE in range, but connected to PSK so show PSK security string
assertThat(entry.getSecurityString(true /* concise */))
.isEqualTo(wifiSecurityShortWpaWpa2);
when(mMockWifiInfo.getCurrentSecurityType()).thenReturn(SECURITY_TYPE_SAE);
- entry.updateConnectionInfo(mMockWifiInfo, mMockNetworkInfo);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
// Both PSK and SAE in range, but connected to SAE so show SAE security string
assertThat(entry.getSecurityString(true /* concise */))
@@ -917,51 +960,106 @@ public class StandardWifiEntryTest {
public void testGetMeteredChoice_afterSetMeteredChoice_getCorrectValue() {
StandardWifiEntry entry =
getSavedStandardWifiEntry(WifiConfiguration.SECURITY_TYPE_PSK);
+ WifiConfiguration oldConfig = new WifiConfiguration(entry.getWifiConfiguration());
+ assertThat(oldConfig.meteredOverride).isEqualTo(WifiConfiguration.METERED_OVERRIDE_NONE);
+ // Simulate the privacy being updated by someone else, but we haven't gotten the
+ // CONFIGURED_NETWORKS_CHANGED broadcast yet.
+ assertThat(oldConfig.macRandomizationSetting).isEqualTo(
+ WifiConfiguration.RANDOMIZATION_AUTO);
+ oldConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(oldConfig));
entry.setMeteredChoice(WifiEntry.METERED_CHOICE_METERED);
assertThat(entry.getMeteredChoice()).isEqualTo(WifiEntry.METERED_CHOICE_METERED);
+ ArgumentCaptor<WifiConfiguration> configCaptor =
+ ArgumentCaptor.forClass(WifiConfiguration.class);
+ verify(mMockWifiManager).save(configCaptor.capture(), any());
+ // Metered choice value should be updated.
+ assertThat(configCaptor.getValue().meteredOverride)
+ .isEqualTo(WifiConfiguration.METERED_OVERRIDE_METERED);
+ // Privacy value should not be overwritten by our stale config.
+ assertThat(configCaptor.getValue().macRandomizationSetting)
+ .isEqualTo(WifiConfiguration.RANDOMIZATION_NONE);
+ }
+
+ @Test
+ public void testGetPrivacy_afterSetPrivacy_getCorrectValue() {
+ StandardWifiEntry entry =
+ getSavedStandardWifiEntry(WifiConfiguration.SECURITY_TYPE_PSK);
+ WifiConfiguration oldConfig = new WifiConfiguration(entry.getWifiConfiguration());
+ assertThat(oldConfig.macRandomizationSetting).isEqualTo(
+ WifiConfiguration.RANDOMIZATION_AUTO);
+ // Simulate the metered choice being updated by someone else, but we haven't gotten the
+ // CONFIGURED_NETWORKS_CHANGED broadcast yet.
+ assertThat(oldConfig.meteredOverride).isEqualTo(WifiConfiguration.METERED_OVERRIDE_NONE);
+ oldConfig.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED;
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(oldConfig));
+
+ entry.setPrivacy(WifiEntry.PRIVACY_DEVICE_MAC);
+
+ assertThat(entry.getMeteredChoice()).isEqualTo(WifiEntry.METERED_CHOICE_METERED);
+ ArgumentCaptor<WifiConfiguration> configCaptor =
+ ArgumentCaptor.forClass(WifiConfiguration.class);
+ verify(mMockWifiManager).save(configCaptor.capture(), any());
+ // Privacy choice value should be updated.
+ assertThat(configCaptor.getValue().macRandomizationSetting)
+ .isEqualTo(WifiConfiguration.RANDOMIZATION_NONE);
+ // Metered choice value should not be overwritten by our stale config.
+ assertThat(configCaptor.getValue().meteredOverride)
+ .isEqualTo(WifiConfiguration.METERED_OVERRIDE_METERED);
}
+
@Test
public void testCanSignIn_captivePortalCapability_returnsTrue() {
- final StandardWifiEntry entry = new StandardWifiEntry(
+ WifiConfiguration wifiConfig = new WifiConfiguration();
+ wifiConfig.SSID = "\"ssid\"";
+ wifiConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
+ wifiConfig.networkId = 1;
+ when(mMockWifiInfo.getNetworkId()).thenReturn(wifiConfig.networkId);
+
+ when(mMockNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
+ StandardWifiEntry entry = new StandardWifiEntry(
mMockInjector, mMockContext, mTestHandler,
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_OPEN),
- null, Arrays.asList(
- buildScanResult("ssid", "bssid0", 0, TestUtils.GOOD_RSSI)),
- mMockWifiManager, false /* forSavedNetworksPage */);
- NetworkCapabilities captivePortalCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL).build();
- entry.updateNetworkCapabilities(captivePortalCapabilities);
+ Collections.singletonList(wifiConfig), null, mMockWifiManager,
+ false /* forSavedNetworksPage */);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.canSignIn()).isTrue();
}
@Test
public void testUpdateNetworkCapabilities_userConnect_autoOpenCaptivePortalOnce() {
- when(mMockContext.getSystemService(ConnectivityManager.class))
- .thenReturn(mMockConnectivityManager);
- final StandardWifiEntry entry = new StandardWifiEntry(
+ WifiConfiguration wifiConfig = new WifiConfiguration();
+ wifiConfig.SSID = "\"ssid\"";
+ wifiConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
+ wifiConfig.networkId = 1;
+ when(mMockWifiInfo.getNetworkId()).thenReturn(wifiConfig.networkId);
+
+ when(mMockNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
+ StandardWifiEntry entry = new StandardWifiEntry(
mMockInjector, mMockContext, mTestHandler,
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_OPEN),
- null, Arrays.asList(
- buildScanResult("ssid", "bssid0", 0, TestUtils.GOOD_RSSI)),
- mMockWifiManager, false /* forSavedNetworksPage */);
- NetworkCapabilities captivePortalCapabilities = new NetworkCapabilities.Builder()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL).build();
+ Collections.singletonList(wifiConfig), null, mMockWifiManager,
+ false /* forSavedNetworksPage */);
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
// Simulate user tapping on the network and receiving captive portal capabilities.
// This should trigger the captive portal app.
entry.connect(null /* callback */);
- entry.updateNetworkCapabilities(captivePortalCapabilities);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
// Update network capabilities again. This should not trigger the captive portal app.
- entry.updateNetworkCapabilities(captivePortalCapabilities);
+ entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
} finally {
@@ -1006,7 +1104,6 @@ public class StandardWifiEntryTest {
@Test
public void testShouldEditBeforeConnect_authenticationFailure_returnTrue() {
- // Test DISABLED_AUTHENTICATION_FAILURE.
WifiConfiguration wifiConfig = spy(new WifiConfiguration());
wifiConfig.SSID = "\"ssid\"";
wifiConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
@@ -1015,38 +1112,68 @@ public class StandardWifiEntryTest {
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
Collections.singletonList(wifiConfig), null, mMockWifiManager,
false /* forSavedNetworksPage */);
- NetworkSelectionStatus.Builder statusBuilder = new NetworkSelectionStatus.Builder();
- NetworkSelectionStatus networkSelectionStatus = spy(statusBuilder.setNetworkSelectionStatus(
- NETWORK_SELECTION_TEMPORARY_DISABLED)
- .setNetworkSelectionDisableReason(
- DISABLED_AUTHENTICATION_FAILURE)
- .build());
- doReturn(1).when(networkSelectionStatus).getDisableReasonCounter(
- DISABLED_AUTHENTICATION_FAILURE);
- doReturn(true).when(networkSelectionStatus).hasEverConnected();
- doReturn(networkSelectionStatus).when(wifiConfig).getNetworkSelectionStatus();
+ NetworkSelectionStatus networkSelectionStatus = mock(NetworkSelectionStatus.class);
+ when(wifiConfig.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus);
+ String saved = "Saved";
+ when(mMockContext.getString(R.string.wifitrackerlib_wifi_disconnected)).thenReturn(saved);
+ String separator = " / ";
+ when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
+ .thenReturn(separator);
+ String disabledPasswordFailure = "disabledPasswordFailure";
+ when(mMockContext.getString(R.string.wifitrackerlib_wifi_disabled_password_failure))
+ .thenReturn(disabledPasswordFailure);
+ String checkPasswordTryAgain = "checkPasswordTryAgain";
+ when(mMockContext.getString(R.string.wifitrackerlib_wifi_check_password_try_again))
+ .thenReturn(checkPasswordTryAgain);
+
+ // Test DISABLED_AUTHENTICATION_FAILURE for never connected network
+ when(networkSelectionStatus.hasEverConnected()).thenReturn(false);
+ when(networkSelectionStatus.getNetworkSelectionStatus())
+ .thenReturn(NETWORK_SELECTION_ENABLED);
+ when(networkSelectionStatus.getDisableReasonCounter(DISABLED_AUTHENTICATION_FAILURE))
+ .thenReturn(1);
+ assertThat(entry.shouldEditBeforeConnect()).isTrue();
+ assertThat(entry.getSummary()).isEqualTo(saved + separator + disabledPasswordFailure);
+
+ // Test DISABLED_AUTHENTICATION_FAILURE for a previously connected network
+ when(networkSelectionStatus.hasEverConnected()).thenReturn(true);
+ when(networkSelectionStatus.getNetworkSelectionStatus())
+ .thenReturn(NETWORK_SELECTION_PERMANENTLY_DISABLED);
+ when(networkSelectionStatus.getNetworkSelectionDisableReason())
+ .thenReturn(DISABLED_AUTHENTICATION_FAILURE);
+ when(wifiConfig.hasNoInternetAccess()).thenReturn(false);
assertThat(entry.shouldEditBeforeConnect()).isTrue();
+ assertThat(entry.getSummary()).isEqualTo(saved + separator + disabledPasswordFailure);
+
+ // Test DISABLED_CONSECUTIVE_FAILURES with some DISABLED_AUTHENTICATION_FAILURE
+ when(networkSelectionStatus.hasEverConnected()).thenReturn(false);
+ when(networkSelectionStatus.getNetworkSelectionStatus())
+ .thenReturn(NETWORK_SELECTION_PERMANENTLY_DISABLED);
+ when(networkSelectionStatus.getNetworkSelectionDisableReason())
+ .thenReturn(DISABLED_CONSECUTIVE_FAILURES);
+ when(networkSelectionStatus.getDisableReasonCounter(DISABLED_AUTHENTICATION_FAILURE))
+ .thenReturn(3);
+ assertThat(entry.shouldEditBeforeConnect()).isTrue();
+ assertThat(entry.getSummary()).isEqualTo(saved + separator + disabledPasswordFailure);
// Test DISABLED_BY_WRONG_PASSWORD.
- networkSelectionStatus = spy(statusBuilder.setNetworkSelectionStatus(
- NETWORK_SELECTION_PERMANENTLY_DISABLED)
- .setNetworkSelectionDisableReason(DISABLED_BY_WRONG_PASSWORD)
- .build());
- doReturn(1).when(networkSelectionStatus).getDisableReasonCounter(
- DISABLED_BY_WRONG_PASSWORD);
-
+ when(networkSelectionStatus.hasEverConnected()).thenReturn(false);
+ when(networkSelectionStatus.getNetworkSelectionStatus())
+ .thenReturn(NETWORK_SELECTION_PERMANENTLY_DISABLED);
+ when(networkSelectionStatus.getNetworkSelectionDisableReason())
+ .thenReturn(DISABLED_BY_WRONG_PASSWORD);
assertThat(entry.shouldEditBeforeConnect()).isTrue();
+ assertThat(entry.getSummary()).isEqualTo(saved + separator + checkPasswordTryAgain);
// Test DISABLED_AUTHENTICATION_NO_CREDENTIALS.
- networkSelectionStatus = spy(statusBuilder.setNetworkSelectionStatus(
- NETWORK_SELECTION_PERMANENTLY_DISABLED)
- .setNetworkSelectionDisableReason(DISABLED_AUTHENTICATION_NO_CREDENTIALS)
- .build());
- doReturn(1).when(networkSelectionStatus).getDisableReasonCounter(
- DISABLED_AUTHENTICATION_NO_CREDENTIALS);
-
+ when(networkSelectionStatus.hasEverConnected()).thenReturn(false);
+ when(networkSelectionStatus.getNetworkSelectionStatus())
+ .thenReturn(NETWORK_SELECTION_PERMANENTLY_DISABLED);
+ when(networkSelectionStatus.getNetworkSelectionDisableReason())
+ .thenReturn(DISABLED_AUTHENTICATION_NO_CREDENTIALS);
assertThat(entry.shouldEditBeforeConnect()).isTrue();
+ assertThat(entry.getSummary()).isEqualTo(saved + separator + disabledPasswordFailure);
}
@Test
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/TestUtils.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/TestUtils.java
index 85d98ccd2..71102dd8d 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/TestUtils.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/TestUtils.java
@@ -57,6 +57,13 @@ class TestUtils {
return result;
}
+ static ScanResult buildScanResult(
+ String utf8Ssid, String bssid, long timestampMillis, String securityTypesString) {
+ final ScanResult result = buildScanResult(utf8Ssid, bssid, timestampMillis);
+ result.capabilities = securityTypesString;
+ return result;
+ }
+
static WifiConfiguration buildWifiConfiguration(String utf8Ssid) {
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"" + utf8Ssid + "\"";
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java
index f7d029e2d..91002dd78 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/UtilsTest.java
@@ -36,6 +36,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -50,15 +52,16 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.net.NetworkInfo;
import android.net.ConnectivityDiagnosticsManager;
import android.net.NetworkCapabilities;
+import android.net.wifi.MloLink;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiScanner;
import android.os.Handler;
import android.os.PersistableBundle;
import android.os.test.TestLooper;
@@ -69,6 +72,8 @@ import android.telephony.TelephonyManager;
import android.text.SpannableString;
import android.text.style.ClickableSpan;
+import androidx.core.os.BuildCompat;
+
import com.android.wifitrackerlib.shadow.ShadowSystem;
import org.junit.Before;
@@ -120,6 +125,12 @@ public class UtilsTest {
private static final String TEST_CARRIER_NAME = "carrierName";
+ private static final String BAND_SEPARATOR = ", ";
+ private static final String BAND_UNKNOWN = "Unknown";
+ private static final String BAND_24_GHZ = "2.4 GHz";
+ private static final String BAND_5_GHZ = "5 GHz";
+ private static final String BAND_6_GHZ = "6 GHz";
+
@Mock private WifiTrackerInjector mMockInjector;
@Mock private Context mMockContext;
@Mock private Resources mMockResources;
@@ -134,6 +145,12 @@ public class UtilsTest {
private Handler mTestHandler;
+ private StandardWifiEntry getStandardWifiEntry(WifiConfiguration config) {
+ return new StandardWifiEntry(mMockInjector, mMockContext, mTestHandler,
+ new StandardWifiEntryKey(config), Collections.singletonList(config), null,
+ mMockWifiManager, false /* forSavedNetworksPage */);
+ }
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -156,6 +173,16 @@ public class UtilsTest {
when(mMockContext.getContentResolver()).thenReturn(mContentResolver);
when(mContentResolver.getUserId()).thenReturn(0);
when(mMockInjector.getNoAttributionAnnotationPackages()).thenReturn(Collections.emptySet());
+ when(mMockResources.getString(R.string.wifitrackerlib_multiband_separator))
+ .thenReturn(BAND_SEPARATOR);
+ when(mMockResources.getString(R.string.wifitrackerlib_wifi_band_unknown))
+ .thenReturn(BAND_UNKNOWN);
+ when(mMockResources.getString(R.string.wifitrackerlib_wifi_band_24_ghz))
+ .thenReturn(BAND_24_GHZ);
+ when(mMockResources.getString(R.string.wifitrackerlib_wifi_band_5_ghz))
+ .thenReturn(BAND_5_GHZ);
+ when(mMockResources.getString(R.string.wifitrackerlib_wifi_band_6_ghz))
+ .thenReturn(BAND_6_GHZ);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(STRING_ARRAY_WIFI_STATUS);
when(mMockResources.getIdentifier(eq("network_available_sign_in"), eq("string"),
@@ -622,15 +649,79 @@ public class UtilsTest {
mMockInjector, mMockContext, noAttributionConfig, true, false)).isEmpty();
}
- private StandardWifiEntry getStandardWifiEntry(WifiConfiguration config) {
- final StandardWifiEntry entry = new StandardWifiEntry(mMockInjector, mMockContext,
- mTestHandler, new StandardWifiEntryKey(config), Collections.singletonList(config),
- null, mMockWifiManager, false /* forSavedNetworksPage */);
- final WifiInfo mockWifiInfo = mock(WifiInfo.class);
- final NetworkInfo mockNetworkInfo = mock(NetworkInfo.class);
+ @Test
+ public void testWifiInfoBandString_multipleMloLinks_returnsMultipleBands() {
+ assumeTrue(BuildCompat.isAtLeastU());
+
+ List<MloLink> mloLinks = new ArrayList<>();
- entry.updateConnectionInfo(mockWifiInfo, mockNetworkInfo);
- return entry;
+ MloLink linkUnspecified = mock(MloLink.class);
+ when(linkUnspecified.getBand()).thenReturn(WifiScanner.WIFI_BAND_UNSPECIFIED);
+ // Should filter out idle links.
+ when(linkUnspecified.getState()).thenReturn(MloLink.MLO_LINK_STATE_IDLE);
+ mloLinks.add(linkUnspecified);
+
+ MloLink link24Ghz = mock(MloLink.class);
+ when(link24Ghz.getBand()).thenReturn(WifiScanner.WIFI_BAND_24_GHZ);
+ when(link24Ghz.getState()).thenReturn(MloLink.MLO_LINK_STATE_ACTIVE);
+ mloLinks.add(link24Ghz);
+ // Should filter out duplicate bands.
+ mloLinks.add(link24Ghz);
+
+ MloLink link5Ghz = mock(MloLink.class);
+ when(link5Ghz.getBand()).thenReturn(WifiScanner.WIFI_BAND_5_GHZ);
+ when(link5Ghz.getState()).thenReturn(MloLink.MLO_LINK_STATE_ACTIVE);
+ mloLinks.add(link5Ghz);
+
+ MloLink link6Ghz = mock(MloLink.class);
+ when(link6Ghz.getBand()).thenReturn(WifiScanner.WIFI_BAND_6_GHZ);
+ when(link6Ghz.getState()).thenReturn(MloLink.MLO_LINK_STATE_ACTIVE);
+ mloLinks.add(link6Ghz);
+
+ WifiInfo wifiInfo = mock(WifiInfo.class);
+ when(wifiInfo.getWifiStandard()).thenReturn(ScanResult.WIFI_STANDARD_11BE);
+ when(wifiInfo.getAssociatedMloLinks()).thenReturn(mloLinks);
+
+ assertThat(Utils.getBandString(mMockContext, wifiInfo))
+ .isEqualTo("2.4 GHz, 5 GHz, 6 GHz");
+ }
+
+ @Test
+ public void testWifiInfoBandString_noMloLinks_returnsSingleBand() {
+ assumeTrue(BuildCompat.isAtLeastU());
+
+ WifiInfo wifiInfo = mock(WifiInfo.class);
+ when(wifiInfo.getAssociatedMloLinks()).thenReturn(Collections.emptyList());
+
+ when(wifiInfo.getFrequency()).thenReturn(0);
+ assertThat(Utils.getBandString(mMockContext, wifiInfo)).isEqualTo(BAND_UNKNOWN);
+
+ when(wifiInfo.getFrequency()).thenReturn(2400);
+ assertThat(Utils.getBandString(mMockContext, wifiInfo)).isEqualTo(BAND_24_GHZ);
+
+ when(wifiInfo.getFrequency()).thenReturn(5200);
+ assertThat(Utils.getBandString(mMockContext, wifiInfo)).isEqualTo(BAND_5_GHZ);
+
+ when(wifiInfo.getFrequency()).thenReturn(6000);
+ assertThat(Utils.getBandString(mMockContext, wifiInfo)).isEqualTo(BAND_6_GHZ);
+ }
+
+ @Test
+ public void testWifiInfoBandString_lessThanU_returnsSingleBand() {
+ assumeFalse(BuildCompat.isAtLeastU());
+ WifiInfo wifiInfo = mock(WifiInfo.class);
+
+ when(wifiInfo.getFrequency()).thenReturn(0);
+ assertThat(Utils.getBandString(mMockContext, wifiInfo)).isEqualTo(BAND_UNKNOWN);
+
+ when(wifiInfo.getFrequency()).thenReturn(2400);
+ assertThat(Utils.getBandString(mMockContext, wifiInfo)).isEqualTo(BAND_24_GHZ);
+
+ when(wifiInfo.getFrequency()).thenReturn(5200);
+ assertThat(Utils.getBandString(mMockContext, wifiInfo)).isEqualTo(BAND_5_GHZ);
+
+ when(wifiInfo.getFrequency()).thenReturn(6000);
+ assertThat(Utils.getBandString(mMockContext, wifiInfo)).isEqualTo(BAND_6_GHZ);
}
@Test
@@ -770,4 +861,37 @@ public class UtilsTest {
+ STRING_SUMMARY_SEPARATOR + STRING_CONNECTED_LOW_QUALITY
+ STRING_SUMMARY_SEPARATOR + STRING_NO_INTERNET);
}
+
+ @Test
+ public void testGetSingleSecurityTypeFromMultipleSecurityTypes() {
+ // Empty
+ assertThat(Utils.getSingleSecurityTypeFromMultipleSecurityTypes(new ArrayList<>()))
+ .isEqualTo(WifiInfo.SECURITY_TYPE_UNKNOWN);
+ // Single type
+ assertThat(Utils.getSingleSecurityTypeFromMultipleSecurityTypes(
+ Arrays.asList(WifiInfo.SECURITY_TYPE_PSK)))
+ .isEqualTo(WifiInfo.SECURITY_TYPE_PSK);
+ // Open + OWE -> Open
+ assertThat(Utils.getSingleSecurityTypeFromMultipleSecurityTypes(
+ Arrays.asList(WifiInfo.SECURITY_TYPE_OPEN, WifiInfo.SECURITY_TYPE_OWE)))
+ .isEqualTo(WifiInfo.SECURITY_TYPE_OPEN);
+ // PSK + SAE -> PSK
+ assertThat(Utils.getSingleSecurityTypeFromMultipleSecurityTypes(
+ Arrays.asList(WifiInfo.SECURITY_TYPE_SAE, WifiInfo.SECURITY_TYPE_PSK)))
+ .isEqualTo(WifiInfo.SECURITY_TYPE_PSK);
+ // EAP + WPA3-Enterprise -> EAP
+ assertThat(Utils.getSingleSecurityTypeFromMultipleSecurityTypes(
+ Arrays.asList(WifiInfo.SECURITY_TYPE_EAP,
+ WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE)))
+ .isEqualTo(WifiInfo.SECURITY_TYPE_EAP);
+ // Everything else -> first security type on the list.
+ assertThat(Utils.getSingleSecurityTypeFromMultipleSecurityTypes(
+ Arrays.asList(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2,
+ WifiInfo.SECURITY_TYPE_PASSPOINT_R3)))
+ .isEqualTo(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
+ assertThat(Utils.getSingleSecurityTypeFromMultipleSecurityTypes(
+ Arrays.asList(WifiInfo.SECURITY_TYPE_PASSPOINT_R3,
+ WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2)))
+ .isEqualTo(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
+ }
}
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
index d421e6b19..96b3e5459 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
@@ -16,6 +16,10 @@
package com.android.wifitrackerlib;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_SAE;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -24,6 +28,8 @@ import static com.android.wifitrackerlib.TestUtils.GOOD_LEVEL;
import static com.android.wifitrackerlib.TestUtils.GOOD_RSSI;
import static com.android.wifitrackerlib.TestUtils.buildScanResult;
import static com.android.wifitrackerlib.TestUtils.buildWifiConfiguration;
+import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
+import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_DISCONNECTED;
import static com.google.common.truth.Truth.assertThat;
@@ -33,6 +39,7 @@ import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -42,25 +49,38 @@ import android.content.Intent;
import android.content.res.Resources;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.net.TransportInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiScanner;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.KnownNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
import android.os.Handler;
import android.os.test.TestLooper;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
import android.util.Pair;
+import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -74,7 +94,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -91,6 +110,7 @@ public class WifiPickerTrackerTest {
@Mock private Context mMockContext;
@Mock private Resources mMockResources;
@Mock private WifiManager mMockWifiManager;
+ @Mock private WifiScanner mWifiScanner;
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private ConnectivityDiagnosticsManager mMockConnectivityDiagnosticsManager;
@Mock private TelephonyManager mMockTelephonyManager;
@@ -98,8 +118,11 @@ public class WifiPickerTrackerTest {
@Mock private Clock mMockClock;
@Mock private WifiPickerTracker.WifiPickerTrackerCallback mMockCallback;
@Mock private WifiInfo mMockWifiInfo;
- @Mock private NetworkInfo mMockNetworkInfo;
@Mock private Network mMockNetwork;
+ @Mock private NetworkCapabilities mMockNetworkCapabilities;
+ @Mock private NetworkCapabilities mMockVcnNetworkCapabilities;
+ @Mock private LinkProperties mMockLinkProperties;
+ @Mock private SharedConnectivityManager mMockSharedConnectivityManager;
private TestLooper mTestLooper;
@@ -111,6 +134,9 @@ public class WifiPickerTrackerTest {
private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
mDefaultNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+ private final ArgumentCaptor<SharedConnectivityClientCallback>
+ mSharedConnectivityCallbackCaptor =
+ ArgumentCaptor.forClass(SharedConnectivityClientCallback.class);
private WifiPickerTracker createTestWifiPickerTracker() {
final Handler testHandler = new Handler(mTestLooper.getLooper());
@@ -136,7 +162,7 @@ public class WifiPickerTrackerTest {
mTestLooper = new TestLooper();
when(mMockWifiManager.getScanResults()).thenReturn(new ArrayList<>());
- when(mMockWifiManager.getConnectionInfo()).thenReturn(mMockWifiInfo);
+ when(mMockWifiManager.getCurrentNetwork()).thenReturn(mMockNetwork);
when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true);
when(mMockWifiManager.isWpa3SuiteBSupported()).thenReturn(true);
@@ -147,12 +173,36 @@ public class WifiPickerTrackerTest {
.thenReturn(TestUtils.OKAY_LEVEL);
when(mMockWifiManager.calculateSignalLevel(TestUtils.BAD_RSSI))
.thenReturn(TestUtils.BAD_LEVEL);
- when(mMockConnectivityManager.getNetworkInfo(any())).thenReturn(mMockNetworkInfo);
when(mMockClock.millis()).thenReturn(START_MILLIS);
+ when(mMockWifiInfo.isPrimary()).thenReturn(true);
when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(
- NetworkInfo.DetailedState.DISCONNECTED);
+ when(mMockWifiInfo.makeCopy(anyLong())).thenReturn(mMockWifiInfo);
+ when(mMockWifiManager.getConnectionInfo()).thenReturn(mMockWifiInfo);
+ when(mMockNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
+ .thenReturn(true);
+ when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
+ when(mMockVcnNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ // Use a placeholder TransportInfo since VcnTransportInfo is @hide.
+ // NonSdkApiWrapper is mocked to get the WifiInfo from these capabilities.
+ when(mMockVcnNetworkCapabilities.getTransportInfo()).thenReturn(
+ new TransportInfo() {
+ @NonNull
+ @Override
+ public TransportInfo makeCopy(long redactions) {
+ return TransportInfo.super.makeCopy(redactions);
+ }
+ });
+ // A real NetworkCapabilities is needed here in order to create a copy (with location info)
+ // using the NetworkCapabilities constructor in handleOnStart.
+ when(mMockConnectivityManager.getNetworkCapabilities(mMockNetwork))
+ .thenReturn(new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build());
+ when(mMockConnectivityManager.getLinkProperties(mMockNetwork))
+ .thenReturn(mMockLinkProperties);
+ when(mMockSharedConnectivityManager.unregisterCallback(any())).thenReturn(true);
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getSystemService(TelephonyManager.class))
.thenReturn(mMockTelephonyManager);
@@ -160,7 +210,21 @@ public class WifiPickerTrackerTest {
.thenReturn(mMockSubscriptionManager);
when(mMockContext.getSystemService(ConnectivityDiagnosticsManager.class))
.thenReturn(mMockConnectivityDiagnosticsManager);
+ when(mMockContext.getSystemService(WifiScanner.class)).thenReturn(mWifiScanner);
+ when(mMockContext.getSystemService(SharedConnectivityManager.class))
+ .thenReturn(mMockSharedConnectivityManager);
when(mMockContext.getString(anyInt())).thenReturn("");
+ when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status)).thenReturn(
+ new String[]{"", "Scanning", "Connecting", "Authenticating", "Obtaining IP address",
+ "Connected", "Suspended", "Disconnecting", "Unsuccessful", "Blocked",
+ "Temporarily avoiding poor connection"});
+
+ BaseWifiTracker.mEnableSharedConnectivityFeature = true;
+ }
+
+ @After
+ public void tearDown() {
+ BaseWifiTracker.mEnableSharedConnectivityFeature = false;
}
/**
@@ -483,7 +547,6 @@ public class WifiPickerTrackerTest {
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
@@ -507,16 +570,14 @@ public class WifiPickerTrackerTest {
buildScanResult("ssid", "bssid", START_MILLIS)));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0);
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)
- .putExtra(WifiManager.EXTRA_NETWORK_INFO, mMockNetworkInfo));
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
@@ -524,6 +585,76 @@ public class WifiPickerTrackerTest {
}
/**
+ * Tests that an L2 connected network (i.e. from NETWORK_STATE_CHANGED) will correctly be
+ * returned in getConnectedEntry() as the primary network.
+ */
+ @Test
+ public void testGetConnectedEntry_networkL2Connected_returnsConnectedEntry() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
+ buildScanResult("ssid", "bssid", START_MILLIS)));
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockContext).registerReceiver(
+ mBroadcastReceiverCaptor.capture(), any(), any(), any());
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
+ final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0);
+
+ // Simulate an L2 connected network that's still authenticating.
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(-50);
+ NetworkInfo mockNetworkInfo = mock(NetworkInfo.class);
+ when(mockNetworkInfo.getDetailedState())
+ .thenReturn(NetworkInfo.DetailedState.AUTHENTICATING);
+ Intent networkStateChanged = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ networkStateChanged.putExtra(WifiManager.EXTRA_NETWORK_INFO, mockNetworkInfo);
+ mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, networkStateChanged);
+
+ // Network should be returned in getConnectedWifiEntry() even though it's not L3 connected.
+ verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
+// assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(entry);
+ assertThat(entry.isPrimaryNetwork()).isTrue();
+ }
+
+ /**
+ * Tests that connecting to a network will update getConnectedEntry() to return the connected
+ * WifiEntry if the framework times out and gives us an empty list of configs.
+ */
+ @Test
+ public void testGetConnectedEntry_connectToNetworkWithoutConfigs_returnsConnectedEntry() {
+ // Simulate the framework timing out and giving us an empty list of configs.
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.emptyList());
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
+
+ // Populate the correct list of configs.
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(-50);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
+
+ verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNotNull();
+ assertThat(wifiPickerTracker.getConnectedWifiEntry().getTitle()).isEqualTo("ssid");
+ }
+
+ /**
* Tests that disconnecting from a network will update getConnectedEntry() to return null.
*/
@Test
@@ -538,17 +669,12 @@ public class WifiPickerTrackerTest {
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
- when(mMockNetworkInfo.getDetailedState())
- .thenReturn(NetworkInfo.DetailedState.DISCONNECTED);
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)
- .putExtra(WifiManager.EXTRA_NETWORK_INFO, mMockNetworkInfo));
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
@@ -570,7 +696,6 @@ public class WifiPickerTrackerTest {
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
@@ -585,6 +710,63 @@ public class WifiPickerTrackerTest {
}
/**
+ * Tests that a connected WifiEntry's isDefaultNetwork() will reflect updates from the default
+ * network changing.
+ */
+ @Test
+ public void testGetConnectedEntry_defaultNetworkChanges_isDefaultNetworkChanges() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
+ buildScanResult("ssid", "bssid", START_MILLIS)));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(-50);
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockConnectivityManager)
+ .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
+ verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
+ mDefaultNetworkCallbackCaptor.capture(), any());
+ verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
+ mDefaultNetworkCallbackCaptor.capture(), any());
+
+ // No default
+ assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
+
+ // Cell is default
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mock(Network.class),
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
+
+ assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
+
+ // Other Wi-Fi network is default
+ Network otherWifiNetwork = mock(Network.class);
+ WifiInfo otherWifiInfo = mock(WifiInfo.class);
+ when(otherWifiInfo.getNetworkId()).thenReturn(2);
+ NetworkCapabilities otherNetworkCapabilities = mock(NetworkCapabilities.class);
+ when(otherNetworkCapabilities.getTransportInfo()).thenReturn(otherWifiInfo);
+ when(otherNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
+ .thenReturn(true);
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(otherWifiNetwork,
+ otherNetworkCapabilities);
+ assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
+
+ // This Wi-Fi network is default
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
+ mMockNetworkCapabilities);
+ assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isTrue();
+
+ // Lose the default network
+ mDefaultNetworkCallbackCaptor.getValue().onLost(mock(Network.class));
+ assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
+ }
+
+ /**
* Tests that a connected WifiEntry will return "Low quality" as the summary if Wifi is
* validated but cell is the default route.
*/
@@ -610,8 +792,6 @@ public class WifiPickerTrackerTest {
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- when(mMockConnectivityManager.getNetworkInfo(any())).thenReturn(mMockNetworkInfo);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager)
@@ -621,14 +801,13 @@ public class WifiPickerTrackerTest {
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
// Set cellular to be the default network
- mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(Mockito.mock(Network.class),
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
// Trigger a validation callback for the non-primary Wifi network.
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
- doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(any()));
WifiInfo nonPrimaryWifiInfo = Mockito.mock(WifiInfo.class);
when(nonPrimaryWifiInfo.makeCopy(anyLong())).thenReturn(nonPrimaryWifiInfo);
NetworkCapabilities nonPrimaryCap = new NetworkCapabilities.Builder()
@@ -636,7 +815,8 @@ public class WifiPickerTrackerTest {
.setTransportInfo(nonPrimaryWifiInfo)
.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
.build();
- mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, nonPrimaryCap);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mock(Network.class), nonPrimaryCap);
} finally {
session.finishMocking();
}
@@ -644,19 +824,29 @@ public class WifiPickerTrackerTest {
// Non-primary Wifi network validation should be ignored.
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isNotEqualTo(lowQuality);
- // Trigger a validation callback for the primary Wifi network.
- WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
- when(primaryWifiInfo.isPrimary()).thenReturn(true);
- when(primaryWifiInfo.makeCopy(anyLong())).thenReturn(primaryWifiInfo);
- NetworkCapabilities primaryCap = new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .setTransportInfo(primaryWifiInfo)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
- .build();
- mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, primaryCap);
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
// Cell default + primary network validation should trigger low quality
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isEqualTo(lowQuality);
+
+ // Cell + VPN is default should not trigger low quality, since the VPN underlying network is
+ // determined by the VPN app and not whether Wi-Fi is low quality or not.
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(Mockito.mock(Network.class),
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
+ assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isNotEqualTo(lowQuality);
+
+ // Set Cell to the default but then lose the default network. Low quality should disappear
+ // since cell default was lost.
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(Mockito.mock(Network.class),
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
+ mDefaultNetworkCallbackCaptor.getValue().onLost(mock(Network.class));
+ assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
}
/**
@@ -675,14 +865,6 @@ public class WifiPickerTrackerTest {
.thenReturn(checkingForInternetAccess);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
- WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
- when(primaryWifiInfo.isPrimary()).thenReturn(true);
- when(primaryWifiInfo.makeCopy(anyLong())).thenReturn(primaryWifiInfo);
- NetworkCapabilities primaryCap = new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .setTransportInfo(primaryWifiInfo)
- .build();
- when(mMockConnectivityManager.getNetworkCapabilities(any())).thenReturn(primaryCap);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
@@ -694,8 +876,6 @@ public class WifiPickerTrackerTest {
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- when(mMockConnectivityManager.getNetworkInfo(any())).thenReturn(mMockNetworkInfo);
ArgumentCaptor<ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback>
diagnosticsCallbackCaptor = ArgumentCaptor.forClass(
ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback.class);
@@ -705,21 +885,26 @@ public class WifiPickerTrackerTest {
.registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityDiagnosticsManager).registerConnectivityDiagnosticsCallback(
any(), any(), diagnosticsCallbackCaptor.capture());
+ verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
+ mDefaultNetworkCallbackCaptor.capture(), any());
+ verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
+ mDefaultNetworkCallbackCaptor.capture(), any());
// Still checking for internet access.
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary())
.isEqualTo(checkingForInternetAccess);
// Trigger a validation callback and connectivity report for the primary Wifi network.
- primaryCap = new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .setTransportInfo(primaryWifiInfo)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
- .build();
- mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, primaryCap);
+ when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
ConnectivityDiagnosticsManager.ConnectivityReport report = mock(
ConnectivityDiagnosticsManager.ConnectivityReport.class);
+ when(report.getNetwork()).thenReturn(mMockNetwork);
diagnosticsCallbackCaptor.getValue().onConnectivityReportAvailable(report);
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
// Now we're fully connected
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isEqualTo("Connected");
@@ -741,14 +926,6 @@ public class WifiPickerTrackerTest {
.thenReturn(connectedToDevice);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
- WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
- when(primaryWifiInfo.isPrimary()).thenReturn(true);
- when(primaryWifiInfo.makeCopy(anyLong())).thenReturn(primaryWifiInfo);
- NetworkCapabilities primaryCap = new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .setTransportInfo(primaryWifiInfo)
- .build();
- when(mMockConnectivityManager.getNetworkCapabilities(any())).thenReturn(primaryCap);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = spy(new WifiConfiguration());
@@ -761,8 +938,6 @@ public class WifiPickerTrackerTest {
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- when(mMockConnectivityManager.getNetworkInfo(any())).thenReturn(mMockNetworkInfo);
ArgumentCaptor<ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback>
diagnosticsCallbackCaptor = ArgumentCaptor.forClass(
ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback.class);
@@ -777,13 +952,11 @@ public class WifiPickerTrackerTest {
.isEqualTo(connectedToDevice);
// Trigger a no-validation callback and connectivity report for the primary Wifi network.
- primaryCap = new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .setTransportInfo(primaryWifiInfo)
- .build();
- mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, primaryCap);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
ConnectivityDiagnosticsManager.ConnectivityReport report = mock(
ConnectivityDiagnosticsManager.ConnectivityReport.class);
+ when(report.getNetwork()).thenReturn(mMockNetwork);
diagnosticsCallbackCaptor.getValue().onConnectivityReportAvailable(report);
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary())
@@ -791,6 +964,69 @@ public class WifiPickerTrackerTest {
}
/**
+ * Tests that getConnectedEntry() will return the correct primary network after an MBB sequence.
+ */
+ @Test
+ public void testGetConnectedEntry_mbbFlow_matchesNewPrimary() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ final WifiConfiguration mbbConfig = new WifiConfiguration();
+ mbbConfig.SSID = "\"otherSsid\"";
+ mbbConfig.networkId = 2;
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Arrays.asList(config, mbbConfig));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(config.networkId);
+ when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
+
+ // Start off connected
+ WifiEntry originalConnectedEntry = wifiPickerTracker.getConnectedWifiEntry();
+ assertThat(originalConnectedEntry).isNotNull();
+ assertThat(originalConnectedEntry.getTitle()).isEqualTo("ssid");
+
+ MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
+ try {
+ // MBB network connected but not primary yet.
+ Network mbbNetwork = mock(Network.class);
+ NetworkCapabilities mbbNetworkCapabilities = mock(NetworkCapabilities.class);
+ WifiInfo mbbWifiInfo = mock(WifiInfo.class);
+ when(mbbWifiInfo.getNetworkId()).thenReturn(mbbConfig.networkId);
+ when(mbbWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
+ when(mbbNetworkCapabilities.getTransportInfo()).thenReturn(mbbWifiInfo);
+ doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(mbbWifiInfo));
+ mNetworkCallbackCaptor.getValue()
+ .onCapabilitiesChanged(mbbNetwork, mbbNetworkCapabilities);
+ // Original network should still be connected.
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(originalConnectedEntry);
+
+ // Original network becomes non-primary and MBB network becomes primary.
+ doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(mMockWifiInfo));
+ mNetworkCallbackCaptor.getValue()
+ .onCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
+ doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(mbbWifiInfo));
+ mNetworkCallbackCaptor.getValue()
+ .onCapabilitiesChanged(mbbNetwork, mbbNetworkCapabilities);
+ // MBB network should be connected now.
+ WifiEntry newConnectedEntry = wifiPickerTracker.getConnectedWifiEntry();
+ assertThat(newConnectedEntry).isNotNull();
+ assertThat(newConnectedEntry.getTitle()).isEqualTo("otherSsid");
+ assertThat(originalConnectedEntry.getConnectedState())
+ .isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+
+ // Original network is lost. MBB network should still be connected
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(newConnectedEntry);
+ } finally {
+ session.finishMocking();
+ }
+ }
+
+ /**
* Tests that a PasspointWifiEntry is returned when Passpoint scans are visible.
*/
@Test
@@ -817,7 +1053,7 @@ public class WifiPickerTrackerTest {
final WifiConfiguration wifiConfig = spy(new WifiConfiguration());
when(wifiConfig.getKey()).thenReturn(passpointConfig.getUniqueId());
- final Map<Integer, List<ScanResult>> mapping = new HashMap<>();
+ final Map<Integer, List<ScanResult>> mapping = new ArrayMap<>();
mapping.put(WifiManager.PASSPOINT_HOME_NETWORK, Collections.singletonList(passpointScan));
List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> allMatchingWifiConfigs =
Collections.singletonList(new Pair<>(wifiConfig, mapping));
@@ -852,7 +1088,7 @@ public class WifiPickerTrackerTest {
when(wifiConfig.getKey()).thenReturn(passpointConfig.getUniqueId());
when(wifiConfig.isPasspoint()).thenReturn(true);
wifiConfig.networkId = 1;
- final Map<Integer, List<ScanResult>> mapping = new HashMap<>();
+ final Map<Integer, List<ScanResult>> mapping = new ArrayMap<>();
mapping.put(WifiManager.PASSPOINT_HOME_NETWORK, Collections.singletonList(
buildScanResult("ssid", "bssid", START_MILLIS)));
List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> allMatchingWifiConfigs =
@@ -862,8 +1098,8 @@ public class WifiPickerTrackerTest {
.thenReturn(Collections.singletonList(wifiConfig));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
assertThat(wifiPickerTracker.getWifiEntries()).isNotEmpty();
final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0);
@@ -871,10 +1107,8 @@ public class WifiPickerTrackerTest {
when(mMockWifiInfo.getPasspointFqdn()).thenReturn("fqdn");
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)
- .putExtra(WifiManager.EXTRA_NETWORK_INFO, mMockNetworkInfo));
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(entry);
@@ -897,7 +1131,7 @@ public class WifiPickerTrackerTest {
.thenReturn(Collections.singletonList(passpointConfig));
final WifiConfiguration wifiConfig = spy(new WifiConfiguration());
when(wifiConfig.getKey()).thenReturn(passpointConfig.getUniqueId());
- final Map<Integer, List<ScanResult>> mapping = new HashMap<>();
+ final Map<Integer, List<ScanResult>> mapping = new ArrayMap<>();
mapping.put(WifiManager.PASSPOINT_HOME_NETWORK, Collections.singletonList(
buildScanResult("ssid", "bssid", START_MILLIS)));
List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> allMatchingWifiConfigs =
@@ -938,7 +1172,7 @@ public class WifiPickerTrackerTest {
.thenReturn(Collections.singletonList(passpointConfig));
final WifiConfiguration wifiConfig = spy(new WifiConfiguration());
when(wifiConfig.getKey()).thenReturn(passpointConfig.getUniqueId());
- final Map<Integer, List<ScanResult>> mapping = new HashMap<>();
+ final Map<Integer, List<ScanResult>> mapping = new ArrayMap<>();
mapping.put(WifiManager.PASSPOINT_HOME_NETWORK, Collections.singletonList(
buildScanResult("ssid", "bssid", START_MILLIS)));
List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> allMatchingWifiConfigs =
@@ -995,8 +1229,6 @@ public class WifiPickerTrackerTest {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
List<WifiEntry> entries = wifiPickerTracker.getWifiEntries();
assertThat(entries.size()).isEqualTo(7);
@@ -1175,12 +1407,13 @@ public class WifiPickerTrackerTest {
Arrays.asList(suggestionConfig));
when(mMockWifiInfo.getNetworkId()).thenReturn(suggestionConfig.networkId);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
WifiEntry suggestionEntry = wifiPickerTracker.getConnectedWifiEntry();
assertThat(suggestionEntry).isNotNull();
@@ -1192,9 +1425,9 @@ public class WifiPickerTrackerTest {
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
// Disconnect from network to verify its usershareability in the picker list
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION));
- mTestLooper.dispatchAll();
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
// Suggestion entry should be in picker list now
suggestionEntry = wifiPickerTracker.getWifiEntries().get(0);
@@ -1230,13 +1463,10 @@ public class WifiPickerTrackerTest {
when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(fqdn);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry().getTitle()).isEqualTo(friendlyName);
@@ -1271,7 +1501,6 @@ public class WifiPickerTrackerTest {
when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(fqdn);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
@@ -1306,35 +1535,148 @@ public class WifiPickerTrackerTest {
Arrays.asList(requestConfig1, requestConfig2));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
// WifiInfo has network id 1, so the connected entry should correspond to request 1
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSsid()).isEqualTo("ssid1");
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
when(mMockWifiInfo.getNetworkId()).thenReturn(2);
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)
- .putExtra(WifiManager.EXTRA_NETWORK_INFO, mMockNetworkInfo));
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
// WifiInfo has network id 2, so the connected entry should correspond to request 2
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSsid()).isEqualTo("ssid2");
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
when(mMockWifiInfo.getNetworkId()).thenReturn(-1);
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)
- .putExtra(WifiManager.EXTRA_NETWORK_INFO, mMockNetworkInfo));
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
// WifiInfo matches no request configs, so the connected entry should be null
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
}
/**
+ * Tests that getActiveWifiEntries() returns the connected primary WifiEntry if we start already
+ * connected to a network.
+ */
+ @Test
+ public void testGetActiveWifiEntries_alreadyConnectedOnStart_returnsConnectedEntry() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(-50);
+
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNotNull();
+ assertThat(wifiPickerTracker.getActiveWifiEntries()).isNotEmpty();
+ assertThat(wifiPickerTracker.getActiveWifiEntries().get(0))
+ .isEqualTo(wifiPickerTracker.getConnectedWifiEntry());
+ }
+
+ /**
+ * Tests that getActiveWifiEntries() returns the connected primary WifiEntry first, and any
+ * secondary OEM networks that are connected.
+ */
+ @Test
+ public void testGetActiveWifiEntries_oemNetworksConnected_returnsPrimaryAndOemNetworks() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ final WifiConfiguration primaryConfig = new WifiConfiguration();
+ primaryConfig.SSID = "\"primary\"";
+ primaryConfig.networkId = 1;
+ final WifiConfiguration oemConfig = new WifiConfiguration();
+ oemConfig.SSID = "\"oem\"";
+ oemConfig.networkId = 2;
+ final WifiConfiguration oemPrivateConfig = new WifiConfiguration();
+ oemPrivateConfig.SSID = "\"oemPrivate\"";
+ oemPrivateConfig.networkId = 3;
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Arrays.asList(primaryConfig, oemConfig, oemPrivateConfig));
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
+
+ MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
+ try {
+ // Connect to primary network
+ when(mMockWifiInfo.getNetworkId()).thenReturn(primaryConfig.networkId);
+ when(mMockWifiInfo.getRssi()).thenReturn(-50);
+ doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(mMockWifiInfo));
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
+
+ // Connect to OEM network
+ Network oemNetwork = mock(Network.class);
+ NetworkCapabilities oemCapabilities = mock(NetworkCapabilities.class);
+ WifiInfo oemWifiInfo = mock(WifiInfo.class);
+ when(oemWifiInfo.getNetworkId()).thenReturn(oemConfig.networkId);
+ when(oemWifiInfo.getRssi()).thenReturn(-50);
+ doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(oemWifiInfo));
+ doReturn(true).when(() -> NonSdkApiWrapper.isOemCapabilities(oemCapabilities));
+ when(oemCapabilities.getTransportInfo()).thenReturn(oemWifiInfo);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ oemNetwork, oemCapabilities);
+
+ WifiEntry primaryWifiEntry = wifiPickerTracker.getActiveWifiEntries().get(0);
+ WifiEntry oemWifiEntry = wifiPickerTracker.getActiveWifiEntries().get(1);
+
+ // Primary should go first, then the OEM network.
+ assertThat(primaryWifiEntry.getTitle()).isEqualTo("primary");
+ assertThat(oemWifiEntry.getTitle()).isEqualTo("oem");
+
+ // Both entries should be connected
+ assertThat(primaryWifiEntry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
+ assertThat(oemWifiEntry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
+
+
+ // Only the primary network should be primary
+ assertThat(primaryWifiEntry.isPrimaryNetwork()).isTrue();
+ assertThat(oemWifiEntry.isPrimaryNetwork()).isFalse();
+
+ // The primary should be returned in getWifiEntries()
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(primaryWifiEntry);
+
+ // Disconnect primary. Secondary OEM network should not be primary
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
+ assertThat(primaryWifiEntry.getConnectedState())
+ .isEqualTo(CONNECTED_STATE_DISCONNECTED);
+ assertThat(wifiPickerTracker.getActiveWifiEntries()).containsExactly(oemWifiEntry);
+ assertThat(oemWifiEntry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
+
+ // OEM network becomes primary.
+ doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(oemWifiInfo));
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ oemNetwork, oemCapabilities);
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(oemWifiEntry);
+ assertThat(wifiPickerTracker.getActiveWifiEntries()).containsExactly(oemWifiEntry);
+ assertThat(oemWifiEntry.isPrimaryNetwork()).isTrue();
+
+ // Disconnect the OEM network.
+ mNetworkCallbackCaptor.getValue().onLost(oemNetwork);
+ assertThat(oemWifiEntry.getConnectedState())
+ .isEqualTo(CONNECTED_STATE_DISCONNECTED);
+ assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
+ assertThat(wifiPickerTracker.getActiveWifiEntries()).isEmpty();
+ } finally {
+ session.finishMocking();
+ }
+ }
+
+ /**
* Tests that SCAN_RESULTS_AVAILABLE_ACTION calls WifiManager#getMatchingOsuProviders()
*/
@Test
@@ -1345,7 +1687,6 @@ public class WifiPickerTrackerTest {
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
-
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
@@ -1361,7 +1702,6 @@ public class WifiPickerTrackerTest {
final int subId = 1;
when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
@@ -1373,7 +1713,7 @@ public class WifiPickerTrackerTest {
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
assertThat(wifiPickerTracker.getMergedCarrierEntry().getConnectedState())
- .isEqualTo(WifiEntry.CONNECTED_STATE_CONNECTED);
+ .isEqualTo(CONNECTED_STATE_CONNECTED);
}
/**
@@ -1571,7 +1911,6 @@ public class WifiPickerTrackerTest {
final int subId = 1;
when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
@@ -1586,13 +1925,12 @@ public class WifiPickerTrackerTest {
mDefaultNetworkCallbackCaptor.capture(), any());
MergedCarrierEntry mergedCarrierEntry = wifiPickerTracker.getMergedCarrierEntry();
assertThat(mergedCarrierEntry.getConnectedState())
- .isEqualTo(WifiEntry.CONNECTED_STATE_CONNECTED);
+ .isEqualTo(CONNECTED_STATE_CONNECTED);
// Wifi isn't default yet, so isDefaultNetwork returns false
assertThat(mergedCarrierEntry.isDefaultNetwork()).isFalse();
- mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
- new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build());
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockNetworkCapabilities);
// Now Wifi is default, so isDefaultNetwork returns true
assertThat(mergedCarrierEntry.isDefaultNetwork()).isTrue();
@@ -1605,9 +1943,6 @@ public class WifiPickerTrackerTest {
@Test
public void testGetMergedCarrierEntry_vcnWifiIsDefault_entryIsDefaultNetwork() {
final int subId = 1;
- when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
- when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
@@ -1616,22 +1951,30 @@ public class WifiPickerTrackerTest {
final Intent intent = new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
intent.putExtra("subscription", subId);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+ verify(mMockConnectivityManager).registerNetworkCallback(
+ any(), mNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
- MergedCarrierEntry mergedCarrierEntry = wifiPickerTracker.getMergedCarrierEntry();
- assertThat(mergedCarrierEntry.getConnectedState())
- .isEqualTo(WifiEntry.CONNECTED_STATE_CONNECTED);
- // Wifi isn't default yet, so isDefaultNetwork returns false
- assertThat(mergedCarrierEntry.isDefaultNetwork()).isFalse();
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
- doReturn(true).when(() -> NonSdkApiWrapper.isVcnOverWifi(any()));
+ // Connect to VCN-over-Wifi network
+ when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
+ when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
+ doReturn(mMockWifiInfo).when(() ->
+ NonSdkApiWrapper.getVcnWifiInfo(mMockVcnNetworkCapabilities));
+ doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(mMockWifiInfo));
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
+ mMockNetwork, mMockVcnNetworkCapabilities);
+ MergedCarrierEntry mergedCarrierEntry = wifiPickerTracker.getMergedCarrierEntry();
+ assertThat(mergedCarrierEntry.getConnectedState())
+ .isEqualTo(CONNECTED_STATE_CONNECTED);
+ // Wifi isn't default yet, so isDefaultNetwork returns false
+ assertThat(mergedCarrierEntry.isDefaultNetwork()).isFalse();
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
- new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
+ mMockVcnNetworkCapabilities);
// Now VCN-over-Wifi is default, so isDefaultNetwork returns true
assertThat(mergedCarrierEntry.isDefaultNetwork()).isTrue();
} finally {
@@ -1659,54 +2002,6 @@ public class WifiPickerTrackerTest {
}
/**
- * Tests that roaming from one network to another will update the new network as the default
- * network if the default route did not change away from Wifi during the roam. This happens if
- * the new network was switched to via MBB.
- */
- @Test
- public void testGetConnectedEntry_roamedButDefaultRouteDidNotChange_entryIsDefaultNetwork() {
- final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
- final WifiConfiguration config1 = new WifiConfiguration();
- config1.SSID = "\"ssid1\"";
- config1.networkId = 1;
- final WifiConfiguration config2 = new WifiConfiguration();
- config2.SSID = "\"ssid2\"";
- config2.networkId = 2;
- when(mMockWifiManager.getPrivilegedConfiguredNetworks())
- .thenReturn(Arrays.asList(config1, config2));
- when(mMockWifiInfo.getNetworkId()).thenReturn(1);
- when(mMockWifiInfo.getRssi()).thenReturn(-50);
- when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
- wifiPickerTracker.onStart();
- mTestLooper.dispatchAll();
- verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
- any(), any(), any());
- verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
- mDefaultNetworkCallbackCaptor.capture(), any());
- verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
- mDefaultNetworkCallbackCaptor.capture(), any());
- // Set the default route to wifi
- mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
- new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .build());
- WifiEntry connectedEntry = wifiPickerTracker.getConnectedWifiEntry();
- assertThat(connectedEntry.getWifiConfiguration()).isEqualTo(config1);
- assertThat(connectedEntry.isDefaultNetwork()).isTrue();
-
- // Connect to new network but don't change the default route
- when(mMockWifiInfo.getNetworkId()).thenReturn(2);
- mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
- new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)
- .putExtra(WifiManager.EXTRA_NETWORK_INFO, mMockNetworkInfo));
-
- // Verify that the newly connected network is still marked as the default network
- connectedEntry = wifiPickerTracker.getConnectedWifiEntry();
- assertThat(connectedEntry.getWifiConfiguration()).isEqualTo(config2);
- assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isTrue();
- }
-
- /**
* Verifies that the BroadcastReceiver and network callbacks are unregistered by the onStop()
* worker thread runnable.
*/
@@ -1747,11 +2042,497 @@ public class WifiPickerTrackerTest {
mDefaultNetworkCallbackCaptor.capture(), any());
wifiPickerTracker.onStop();
- wifiPickerTracker.onDestroyed();
+ wifiPickerTracker.onDestroy();
verify(mMockContext).unregisterReceiver(mBroadcastReceiverCaptor.getValue());
verify(mMockConnectivityManager).unregisterNetworkCallback(
mDefaultNetworkCallbackCaptor.getValue());
verify(mMockConnectivityManager).unregisterNetworkCallback(
mDefaultNetworkCallbackCaptor.getValue());
}
+
+ /**
+ * Tests that the BaseWifiTracker.Scanner continues scanning with WifiManager.startScan() after
+ * the first WifiScanner result is received.
+ */
+ @Test
+ public void testScanner_wifiScannerResultReceived_scannerContinues() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ any(), any(), any());
+ mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
+ new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION).putExtra(
+ WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
+
+ ArgumentCaptor<WifiScanner.ScanListener> mScanListenerCaptor =
+ ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
+ verify(mWifiScanner).startScan(any(), mScanListenerCaptor.capture());
+ mTestLooper.moveTimeForward(SCAN_INTERVAL_MILLIS);
+ mTestLooper.dispatchAll();
+ verify(mMockWifiManager, never()).startScan();
+
+ mScanListenerCaptor.getValue().onResults(null);
+ mTestLooper.dispatchAll();
+ verify(mMockWifiManager).startScan();
+ }
+
+ /**
+ * Tests that the BaseWifiTracker.Scanner continues scanning with WifiManager.startScan() after
+ * the first WifiScanner scan fails.
+ */
+ @Test
+ public void testScanner_wifiScannerFailed_scannerContinues() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ any(), any(), any());
+ mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
+ new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION).putExtra(
+ WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
+
+ ArgumentCaptor<WifiScanner.ScanListener> mScanListenerCaptor =
+ ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
+ verify(mWifiScanner).startScan(any(), mScanListenerCaptor.capture());
+ mTestLooper.moveTimeForward(SCAN_INTERVAL_MILLIS);
+ mTestLooper.dispatchAll();
+ verify(mMockWifiManager, never()).startScan();
+
+ mScanListenerCaptor.getValue().onFailure(0, "Reason");
+ mTestLooper.dispatchAll();
+ verify(mMockWifiManager).startScan();
+ }
+
+ @Test
+ public void testScanner_startAfterOnStop_doesNotStart() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ any(), any(), any());
+
+ // Stop and then get WIFI_STATE_ENABLED afterwards to trigger starting the scanner.
+ wifiPickerTracker.onStop();
+ mTestLooper.dispatchAll();
+ mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
+ new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION)
+ .putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
+
+ // Scanner should not have started
+ verify(mMockWifiManager, never()).startScan();
+
+ // Start again and get WIFI_STATE_ENABLED
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
+ new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION)
+ .putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
+
+ // Scanner should start now
+ verify(mMockWifiManager, never()).startScan();
+ }
+
+ @Test
+ public void testSharedConnectivityManager_onStart_registersCallback() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+ }
+
+ @Test
+ public void testSharedConnectivityManager_onServiceConnected_gettersCalled() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+
+ verify(mMockSharedConnectivityManager).getKnownNetworks();
+ verify(mMockSharedConnectivityManager).getHotspotNetworks();
+ }
+
+ @Test
+ public void testKnownNetworks_noMatchingScanResult_entryNotIncluded() {
+ final KnownNetwork testKnownNetwork = new KnownNetwork.Builder()
+ .setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
+ .setSsid("ssid")
+ .addSecurityType(SECURITY_TYPE_PSK)
+ .addSecurityType(SECURITY_TYPE_SAE)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .build();
+ when(mMockSharedConnectivityManager.getKnownNetworks()).thenReturn(
+ Collections.singletonList(testKnownNetwork));
+ when(mMockWifiManager.getScanResults()).thenReturn(
+ Collections.singletonList(buildScanResult("other_ssid", "bssid", START_MILLIS,
+ "[WEP]")));
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof KnownNetworkEntry).toList()).isEmpty();
+ }
+
+ @Test
+ public void testKnownNetworks_matchingScanResult_entryIncluded() {
+ final KnownNetwork testKnownNetwork = new KnownNetwork.Builder()
+ .setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
+ .setSsid("ssid")
+ .addSecurityType(SECURITY_TYPE_PSK)
+ .addSecurityType(SECURITY_TYPE_SAE)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .build();
+ when(mMockSharedConnectivityManager.getKnownNetworks()).thenReturn(
+ Collections.singletonList(testKnownNetwork));
+ when(mMockWifiManager.getScanResults()).thenReturn(
+ Collections.singletonList(buildScanResult("ssid", "bssid", START_MILLIS,
+ "[PSK/SAE]")));
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof KnownNetworkEntry).toList()).hasSize(1);
+ }
+
+ @Test
+ public void testKnownNetworks_matchingConnectedScanResult_entryNotIncluded() {
+ final KnownNetwork testKnownNetwork = new KnownNetwork.Builder()
+ .setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
+ .setSsid("ssid")
+ .addSecurityType(SECURITY_TYPE_PSK)
+ .addSecurityType(SECURITY_TYPE_SAE)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .build();
+ when(mMockSharedConnectivityManager.getKnownNetworks()).thenReturn(
+ Collections.singletonList(testKnownNetwork));
+ when(mMockWifiManager.getScanResults()).thenReturn(
+ Collections.singletonList(buildScanResult("ssid", "bssid", START_MILLIS,
+ "[PSK/SAE]")));
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
+ when(mMockWifiInfo.getCurrentSecurityType()).thenReturn(SECURITY_TYPE_PSK);
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof KnownNetworkEntry).toList()).isEmpty();
+ assertThat(wifiPickerTracker.getActiveWifiEntries().stream().filter(
+ entry -> entry instanceof KnownNetworkEntry).toList()).isEmpty();
+ assertThat(wifiPickerTracker.getActiveWifiEntries().stream().filter(
+ entry -> entry instanceof StandardWifiEntry).toList()).hasSize(1);
+ }
+
+ @Test
+ public void testKnownNetworks_onKnownNetworkConnectionStatusChanged_matchingEntryCalled() {
+ final KnownNetwork testKnownNetwork1 = new KnownNetwork.Builder()
+ .setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
+ .setSsid("ssid1")
+ .addSecurityType(SECURITY_TYPE_PSK)
+ .addSecurityType(SECURITY_TYPE_SAE)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .build();
+ final KnownNetwork testKnownNetwork2 = new KnownNetwork.Builder()
+ .setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
+ .setSsid("ssid2")
+ .addSecurityType(SECURITY_TYPE_WEP)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Work Phone", "Pixel 6")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(90)
+ .setConnectionStrength(2)
+ .build())
+ .build();
+ final ScanResult testScanResult1 = buildScanResult("ssid1", "bssid1", START_MILLIS,
+ "[PSK/SAE]");
+ final ScanResult testScanResult2 = buildScanResult("ssid2", "bssid2", START_MILLIS,
+ "[WEP]");
+ when(mMockSharedConnectivityManager.getKnownNetworks()).thenReturn(
+ List.of(testKnownNetwork1, testKnownNetwork2));
+ when(mMockWifiManager.getScanResults()).thenReturn(
+ List.of(testScanResult1, testScanResult2));
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+ assertThat(wifiPickerTracker.getWifiEntries()).hasSize(2);
+ assertThat(wifiPickerTracker.getWifiEntries().get(0).getSsid()).isEqualTo("ssid1");
+ final WifiEntry.ConnectCallback connectCallback1 = mock(WifiEntry.ConnectCallback.class);
+ final WifiEntry.ConnectCallback connectCallback2 = mock(WifiEntry.ConnectCallback.class);
+ wifiPickerTracker.getWifiEntries().get(0).connect(connectCallback1);
+ wifiPickerTracker.getWifiEntries().get(1).connect(connectCallback2);
+
+ mSharedConnectivityCallbackCaptor.getValue().onKnownNetworkConnectionStatusChanged(
+ new KnownNetworkConnectionStatus.Builder()
+ .setStatus(KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED)
+ .setKnownNetwork(testKnownNetwork1)
+ .build());
+ mTestLooper.dispatchAll();
+
+ verify(connectCallback1).onConnectResult(anyInt());
+ verify(connectCallback2, never()).onConnectResult(anyInt());
+ }
+
+ @Test
+ public void testHotspotNetworks_noActiveHotspot_virtualEntryIncluded() {
+ final HotspotNetwork testHotspotNetwork = new HotspotNetwork.Builder()
+ .setDeviceId(1)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
+ .setNetworkName("Google Fi")
+ .build();
+ when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
+ Collections.singletonList(testHotspotNetwork));
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof HotspotNetworkEntry).toList()).hasSize(1);
+ WifiEntry hotspotNetworkEntry = wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof HotspotNetworkEntry).findFirst().orElseThrow();
+ assertThat(((HotspotNetworkEntry) hotspotNetworkEntry).getHotspotNetworkEntryKey()
+ .isVirtualEntry()).isTrue();
+ }
+
+ @Test
+ public void testHotspotNetworks_activeHotspot_nonVirtualEntryIncluded() {
+ final HotspotNetwork testHotspotNetwork = new HotspotNetwork.Builder()
+ .setDeviceId(1)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
+ .setNetworkName("Google Fi")
+ .setHotspotSsid("Instant Hotspot abcde")
+ .setHotspotBssid("0a:0b:0c:0d:0e:0f")
+ .addHotspotSecurityType(SECURITY_TYPE_PSK)
+ .addHotspotSecurityType(SECURITY_TYPE_SAE)
+ .build();
+ when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
+ Collections.singletonList(testHotspotNetwork));
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof HotspotNetworkEntry).toList()).hasSize(1);
+ WifiEntry hotspotNetworkEntry = wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof HotspotNetworkEntry).findFirst().orElseThrow();
+ assertThat(((HotspotNetworkEntry) hotspotNetworkEntry).getHotspotNetworkEntryKey()
+ .isVirtualEntry()).isFalse();
+ }
+
+ @Test
+ public void testHotspotNetworks_duplicatesStandardEntry_standardEntryExcluded() {
+ final HotspotNetwork testHotspotNetwork = new HotspotNetwork.Builder()
+ .setDeviceId(1)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
+ .setNetworkName("Google Fi")
+ .setHotspotSsid("Instant Hotspot abcde")
+ .setHotspotBssid("0a:0b:0c:0d:0e:0f")
+ .addHotspotSecurityType(SECURITY_TYPE_PSK)
+ .addHotspotSecurityType(SECURITY_TYPE_SAE)
+ .build();
+ when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
+ Collections.singletonList(testHotspotNetwork));
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ any(), any(), any());
+ when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
+ buildScanResult("Instant Hotspot abcde", "0a:0b:0c:0d:0e:0f", START_MILLIS,
+ "[PSK/SAE]")));
+ mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
+ new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof StandardWifiEntry).toList()).hasSize(1);
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof HotspotNetworkEntry).toList()).isEmpty();
+
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof StandardWifiEntry).toList()).isEmpty();
+ assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
+ entry -> entry instanceof HotspotNetworkEntry).toList()).hasSize(1);
+ }
+
+ @Test
+ public void testHotspotNetworks_duplicatesActiveStandardEntry_standardEntryExcluded() {
+ final HotspotNetwork testHotspotNetwork = new HotspotNetwork.Builder()
+ .setDeviceId(1)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
+ .setNetworkName("Google Fi")
+ .setHotspotSsid("Instant Hotspot abcde")
+ .setHotspotBssid("0a:0b:0c:0d:0e:0f")
+ .addHotspotSecurityType(SECURITY_TYPE_PSK)
+ .addHotspotSecurityType(SECURITY_TYPE_SAE)
+ .build();
+ when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
+ Collections.singletonList(testHotspotNetwork));
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"Instant Hotspot abcde\"";
+ config.BSSID = "0a:0b:0c:0d:0e:0f";
+ config.networkId = 1;
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
+ when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+ .thenReturn(Collections.singletonList(config));
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
+ when(mMockWifiInfo.getBSSID()).thenReturn("0a:0b:0c:0d:0e:0f");
+ when(mMockWifiInfo.getCurrentSecurityType()).thenReturn(SECURITY_TYPE_PSK);
+ when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
+ buildScanResult("Instant Hotspot abcde", "0a:0b:0c:0d:0e:0f", START_MILLIS,
+ "[PSK/SAE]")));
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getActiveWifiEntries().stream().filter(
+ entry -> entry instanceof StandardWifiEntry).toList()).isEmpty();
+ assertThat(wifiPickerTracker.getActiveWifiEntries().stream().filter(
+ entry -> entry instanceof HotspotNetworkEntry).toList()).hasSize(1);
+ }
+
+ @Test
+ public void testHotspotNetworks_onHotspotNetworkConnectionStatusChanged_matchingEntryCalled() {
+ final HotspotNetwork testHotspotNetwork1 = new HotspotNetwork.Builder()
+ .setDeviceId(1)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Phone", "Pixel 7")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(100)
+ .setConnectionStrength(3)
+ .build())
+ .setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
+ .setNetworkName("Google Fi")
+ .build();
+ final HotspotNetwork testHotspotNetwork2 = new HotspotNetwork.Builder()
+ .setDeviceId(2)
+ .setNetworkProviderInfo(new NetworkProviderInfo
+ .Builder("My Work Phone", "Pixel 6")
+ .setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
+ .setBatteryPercentage(90)
+ .setConnectionStrength(2)
+ .build())
+ .setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
+ .setNetworkName("T-Mobile")
+ .build();
+ when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
+ List.of(testHotspotNetwork1, testHotspotNetwork2));
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ wifiPickerTracker.onStart();
+ mTestLooper.dispatchAll();
+ verify(mMockSharedConnectivityManager).registerCallback(any(),
+ mSharedConnectivityCallbackCaptor.capture());
+ mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
+ mTestLooper.dispatchAll();
+
+ assertThat(wifiPickerTracker.getWifiEntries()).hasSize(2);
+ assertThat(((HotspotNetworkEntry) wifiPickerTracker.getWifiEntries().get(0))
+ .getHotspotNetworkEntryKey().getDeviceId()).isEqualTo(1);
+ final WifiEntry.ConnectCallback connectCallback1 = mock(WifiEntry.ConnectCallback.class);
+ final WifiEntry.ConnectCallback connectCallback2 = mock(WifiEntry.ConnectCallback.class);
+ wifiPickerTracker.getWifiEntries().get(0).connect(connectCallback1);
+ wifiPickerTracker.getWifiEntries().get(1).connect(connectCallback2);
+
+ mSharedConnectivityCallbackCaptor.getValue().onHotspotNetworkConnectionStatusChanged(
+ new HotspotNetworkConnectionStatus.Builder()
+ .setStatus(HotspotNetworkConnectionStatus
+ .CONNECTION_STATUS_PROVISIONING_FAILED)
+ .setHotspotNetwork(testHotspotNetwork1)
+ .build());
+ mTestLooper.dispatchAll();
+
+ verify(connectCallback1).onConnectResult(anyInt());
+ verify(connectCallback2, never()).onConnectResult(anyInt());
+ }
}
diff --git a/libwifi_hal/Android.bp b/libwifi_hal/Android.bp
index 2a965ee52..8275d26cc 100644
--- a/libwifi_hal/Android.bp
+++ b/libwifi_hal/Android.bp
@@ -54,6 +54,7 @@ soong_config_string_variable {
"synadhd",
"qcwcn",
"mrvl",
+ "nxp",
"MediaTek",
"realtek",
"emulator",