diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-10-16 20:22:48 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-10-16 20:22:48 +0000 |
commit | ef00e525b188a1e2ebb5cc199471be11f18d0d10 (patch) | |
tree | 889c48fd038beb52cb02bf3509d92e5c5f53971b | |
parent | 5bcedf54c7b09454fbd2150936883f76d0838c94 (diff) | |
parent | 4d2f36d50f6a96c23a98c11617782fde04d4a5c2 (diff) | |
download | wifi-ef00e525b188a1e2ebb5cc199471be11f18d0d10.tar.gz |
Snap for 10957012 from 4d2f36d50f6a96c23a98c11617782fde04d4a5c2 to simpleperf-release
Change-Id: Ibcd504f076f078fe9e6bdbce7f1d2f3b4d23330c
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", |